• 9:输入Model和防止重复Post


     ♣ 视频地址:https://www.bilibili.com/video/av38392956/?p=8

    这节讲输入Model,通过Action传入一个Model,传入进来的Model通常是用来建立数据,或者是修改数据

    想要从客户端传进来Model,那么用户就需要输入Model及Model信息,在Html里输入Model信息通常是使用Form,所有我们想输入的信息肯定得有一个页面并且页面里有Form,所以首先我们需要个方法导航到这个Form页面

    我们可以通过HttpGet请求进入某个Action,然后Action返回含有Form的View就可以了

    那么Form里面的栏位是如何对应Model的各个字段呢,就是通过name属性来对应上的

    • <input type="text" name="FirstName">

    那么对应上之后是怎么传递呢?用http post来做操作

    • HTTP POST

    下面我们做跳转含有Form的页面,首先在Index.cshtml页加上一个跳转

       <div>
            <a asp-action="Create">添加一个学生</a>
        </div>

    然后在HomeController里添加Action

           public IActionResult Create()
            {
                return View();
            }

     接着我们添加Create视图

    @using Tutorial.Web.Model
    @model StudentCreateViewModel
    
        <h1>创建学生</h1>
        <form action="/" method="post">
            <input asp-for="FirstName" /><br /><br />
    
            <input asp-for="LastName" /><br /><br />
    
            <input asp-for="BirthDate" type="date" /><br /><br />
    
            <select asp-for="Gender" asp-items="Html.GetEnumSelectList<Gender>()">
            </select>
            <br /><br />
            <button type="submit" name="save">保存</button>
        </form>

    上面有个Gender类,是我从Model里新加的一个枚举

    namespace Tutorial.Web.Model
    {
        public enum Gender
        {
            男 = 1,
            女 = 0,
            其他 = 2
        }
    }

    我们运行,并且看下它生成的Html代码,可以看到有一个input,它的类型是hidden,它的value是一串token,我们看它的name是“RequestVerificationToken”,它是用来验证这个请求的,用来防止CSRF(跨站请求伪造)

    通过这个token,我们可以保证提交进来的Form是从我的网站的这个页面提交的,而不是一些恶意网站


    下面我们研究如何把Form里的栏位转化成一个Model,实际这个不是我们手动来做的,而是MVC框架自动去做的

    我们Form表单的action的地址就是本身进来的地址/Home/Create,这个地址是HttpGet请求,但是提交之后走的是post请求,HttpPost,所以我们回到HomeController,继续建立一个名为Create,但是Method为HttpPost,这里我们新建了一个ViewModel,就是StudentCreateViewModel,为什么不用Student类呢?

    因为我们要尽可能的保证Form里传递的参数和我们接收类型所有的参数要一直,Student有个Id属性,而Form表单里没有,不一致,所以我们新建一个StudentCreateViewModel来对应Form表单里的各项

      [HttpPost]
            public IActionResult Create(StudentCreateViewModel student)
            {
                var newstudent = new Student
                {
                    FirstName = student.FirstName,
                    LastName = student.LastName,
                    BirthDate = student.BirthDate,
                    Gender = student.Gender
                };
    
                var newModel = _repository.Add(newstudent);
                return View("Detail", newModel);
            }

    然后我们在接口里添加,如下图

    接着我们去服务类InMemoryRepository去实现这个接口

       public Student Add(Student newModel)
            {
                var maxId = _students.Max(x => x.Id);
                newModel.Id = maxId + 1;
                _students.Add(newModel);
                return newModel;
            }

    现在呢,我们来完善下Detail这个视图

    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Detail</title>
    </head>
    <body>
        <div>学生信息</div>
        <div>ID:@Model.Id</div>
        <div>
            姓名:@Model.FirstName @Model.LastName
        </div>
        <div>
            性别:@Model.Gender
        </div>
        <div>
            出生日期:@Model.BirthDate.ToString("yyyy-MM-dd")
        </div>
    
        <a asp-action="Index">返回Home</a>
    </body>
    </html>

    这时候我们就运行,添加会发现在明细页可以展示新添的信息,如下图左,但是点击返回Home的时候,数据却没加载出来,如下图右

      

    那为什么新添的数据没有?这是因为我们注册容器InMemoryRepository的时候选择它的声明周期是Scoped,就是每一次Http请求都会创建一个新的实例,所以在跳回Home页面的时候,又变成了新的请求,那解决办法就是我们把它改成Singleton即可

       public void ConfigureServices(IServiceCollection services)
            {
                services.AddMvc();
                services.AddSingleton<IWelcomeService, WelcomeService>();
                services.AddSingleton<IRepository<Student>, InMemoryRepository>();
            }

     这时候我们再运行看下结果,发现添加进来了,如下图

       

     这时候还会有个问题,就是我们再添加后的页面F5刷新,就会提示重新提交表单,记住这个地址/Home/Create

    这时候我们一直点继续,就会一直提交,就会出现下面的场景,如图

    那接下来我们就来解决,或者避免这个问题

    POST-REDIRECT-GET

    我们post之后,重定向REDIRECT新的页面,然后在新的页面获取GET数据,我们改下代码,如下图

     这时候我们添加一个人,可以看到地址变成了/Home/Detail/4,而不是上面之前那个/Home/Create了,这时候我们刷新页面也不会重新提交表单了

     然后返回Home,可以看到数据都正确,如下图

  • 相关阅读:
    MVC,MVP和MVVM的区别
    将数组里某个属性相同的对象合并成一个数组
    Ajax的理解
    VUE如何关闭Eslint的方法
    数组去重
    vue-router传递参数的几种方式
    密码的显示和隐藏
    "校园易借查询"选题报告
    我的第一个微信好友分析
    数据库实践
  • 原文地址:https://www.cnblogs.com/Codemandyk/p/11016354.html
Copyright © 2020-2023  润新知