【MVC5】7.检查Edit方法和Edit视图

在本节中,您将检查所生成的Edit操作方法和movie controller的视图。但首先需要采取一个简短的更改,使发布日期看起来更好。打开Models\Movie.cs文件并修改为下面代码:


using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }
        public string Title { get; set; }

        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }

    public class MovieDBContext : DbContext
    {
        public DbSet<Movie> Movies { get; set; }
    }
}


你也可以让日期文化像这样:


[Display(Name = "Release Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }



我们将在下一个教程介绍 DataAnnotationsDisplay属性指定为一个字段的名称显示(在这种情况下, "Release Date"而不是 "ReleaseDate")。DataType属性指定的数据类型,在这种情况下,这是一个日期,所以字段中存储的时间信息不显示。   DisplayFormat属性属性是在浏览器中的一个错误,使日期格式不正确的需要。


运行应用程序并浏览到电影控制器。将鼠标指针放在一个Edit链接上,查看它链接到的网址。





Edit链接通过在视图的 Html.ActionLink方法生成Views\Movies\Index.cshtml 视图:


@Html.ActionLink("Edit", "Edit", new { id=item.ID }) 




HTML对象是一个使用system.web.mvc.webviewpage基类属性的辅助工具。其中的ActionLink方法便于动态生成HTML超链接控制器动作方法链接。ActionLink方法的第一个参数是提供链接文本(例如,<a>编辑我</a>)。第二个参数是调用的动作方法的名称(比如这里的 Edit动作)。最后一个参数是一个匿名对象,生成路由数据(比如这里的身份证号 4)。


在以往的影像显示生成的链接是http://localhost:1234/Movies/Edit/4。默认路由(在App_Start\RouteConfig.cs生成)以URL模式 {controller}/{action}/{id}。因此,ASP.NET将http://localhost:1234/Movies/Edit/4变成要求Edit动作方法的控制器的参数与电影ID等于4。从App_Start\RouteConfig.cs文件检查下面的代码。MapRoute方法到正确的控制器和动作方法的HTTP请求路由和供应可选的id参数。MapRoute方法也由 HtmlHelpers 使用如连接产生了控制器使用的URL,动作方法和任何路由数据。


public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", 
            id = UrlParameter.Optional }
    );
}


您也可以使用查询字符串传递动作方法参数。例如,URL的http://localhost:1234/Movies/Edit?ID=3也通过了参数标识为3的电影控制器的Edit动作方法。






打开电影控制器。两个Edit操作方法如下所示。


// GET: /Movies/Edit/5
public ActionResult Edit(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Movie movie = db.Movies.Find(id);
    if (movie == null)
    {
        return HttpNotFound();
    }
    return View(movie);
}

// POST: /Movies/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
    if (ModelState.IsValid)
    {
        db.Entry(movie).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(movie);
}


注意第二个编辑动作方法是之前HttpPost属性。这个属性指定过载的编辑方法只能调用POST请求。你可以应用HttpGet属性于第一个Edit方法,但这不是必要的,因为它是缺省值。(我们会参考操作方法隐式分配HttpGet属性HttpGet方法。)Bind属性是另一个重要的安全机制,防止黑客over-posting数据模型。您应该只包含属性绑定属性,你想改变,你可以读到overposting overposting安全注意和绑定属性。在本教程中使用的简单的模型,我们将绑定在模型中所有的数据。ValidateAntiForgeryToken属性是用来防止伪造请求和配对与@Html.AntiForgeryToken()在编辑视图文件(Views\Movies\Edit.cshtml),部分如下所示:


@model MvcMovie.Models.Movie

@{
    ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()    
    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        @Html.ValidationSummary(true)
        @Html.HiddenFor(model => model.ID)

        <div class="form-group">
            @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Title)
                @Html.ValidationMessageFor(model => model.Title)
            </div>
        </div>


@Html.AntiForgeryToken()生成一个隐藏表单种防伪标记,必须匹配在电影的Edit方法的控制器。你可以阅读更多关于跨站点请求伪造(也称为XSRF或CSRF)在我的教程XSRF / MVC CSRF预防。
HttpGet编辑方法接受电影ID参数,查找电影使用实体框架发现方法,并返回所选电影编辑视图。如果一部电影不能被发现,HttpNotFound返回。当脚手架系统创建编辑视图时,它检查了电影类和创建代码呈现<标记>和<输入>元素的每个属性类。下面的例子显示了生成的编辑视图的visual studio脚手架系统:


@model MvcMovie.Models.Movie

@{
    ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()    
    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        @Html.ValidationSummary(true)
        @Html.HiddenFor(model => model.ID)

        <div class="form-group">
            @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Title)
                @Html.ValidationMessageFor(model => model.Title)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.ReleaseDate, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.ReleaseDate)
                @Html.ValidationMessageFor(model => model.ReleaseDate)
            </div>
        </div>
        @*Genre and Price removed for brevity.*@        
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}



注意,视图模板有一个@ model MvcMovie.Models。电影声明顶部的文件——这指定视图预计模型的视图模板类型的电影。

搭建的代码使用一些辅助方法来简化HTML标记。Html.EditorFor辅助显示字段的名称(“标题”、“ReleaseDate”,“流派”,或“价格”)。Html。EditorFor助手呈现HTML <input>元素。Html.ValidationMessageFor 辅助显示任何验证消息相关的财产。

运行应用程序并导航到 /Movies网址。点击一个Edit链接。在浏览器中,视图页面的源代码的HTML表单元素如下所示。



<form action="/movies/Edit/4" method="post">
   <input name="__RequestVerificationToken" type="hidden" value="UxY6bkQyJCXO3Kn5AXg-6TXxOj6yVBi9tghHaQ5Lq_qwKvcojNXEEfcbn-FGh_0vuw4tS_BRk7QQQHlJp8AP4_X4orVNoQnp2cd8kXhykS01" />  <fieldset class="form-horizontal">
      <legend>Movie</legend>

      <input data-val="true" data-val-number="The field ID must be a number." data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="4" />

      <div class="control-group">
         <label class="control-label" for="Title">Title</label>
         <div class="controls">
            <input class="text-box single-line" id="Title" name="Title" type="text" value="GhostBusters" />
            <span class="field-validation-valid help-inline" data-valmsg-for="Title" data-valmsg-replace="true"></span>
         </div>
      </div>

      <div class="control-group">
         <label class="control-label" for="ReleaseDate">Release Date</label>
         <div class="controls">
            <input class="text-box single-line" data-val="true" data-val-date="The field Release Date must be a date." data-val-required="The Release Date field is required." id="ReleaseDate" name="ReleaseDate" type="date" value="1/1/1984" />
            <span class="field-validation-valid help-inline" data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
         </div>
      </div>

      <div class="control-group">
         <label class="control-label" for="Genre">Genre</label>
         <div class="controls">
            <input class="text-box single-line" id="Genre" name="Genre" type="text" value="Comedy" />
            <span class="field-validation-valid help-inline" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
         </div>
      </div>

      <div class="control-group">
         <label class="control-label" for="Price">Price</label>
         <div class="controls">
            <input class="text-box single-line" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" type="text" value="7.99" />
            <span class="field-validation-valid help-inline" data-valmsg-for="Price" data-valmsg-replace="true"></span>
         </div>
      </div>

      <div class="form-actions no-color">
         <input type="submit" value="Save" class="btn" />
      </div>
   </fieldset>
</form>


<input>元素是在HTML <form>元素的动作属性设置为post /Movies/Edit URL。表单数据将被张贴到服务器时,单击Save按钮。第二行显示了隐藏XSRF @Html.AntiForgeryToken()调用生成的令牌。


处理POST请求

下面的清单显示了HttpPost版本的Edit操作方法。



[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
    if (ModelState.IsValid)
    {
        db.Entry(movie).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(movie);
}


ValidateAntiForgeryToken属性验证XSRF @Html.AntiForgeryToken()调用生成的令牌在视图中。


 ASP.NET MVC模型绑定器将发布表单值并创建一个电影作为电影参数传递的对象。ModelState.IsValid方法验证表单中提交的数据可以用来修改(编辑或更新)电影对象。如果数据是有效的,电影数据保存到电影db(MovieDBContext实例)的集合。新电影的数据保存到数据库中通过调用MovieDBContext中的SaveChanges方法。在保存数据,代码将用户重定向到索引MoviesController类的动作方法,它显示电影集合,包括相应的改变。


一旦客户端验证确定一个字段的值是无效的,显示一个错误消息。如果禁用JavaScript,您不会有客户端验证但服务器会检测到这个值是无效的,和表单的值将被显示错误消息。后在本教程中我们更详细地检查验证。


 Html.ValidationMessageFor协助Edit.cshtml视图模板中显示适当的错误消息。






所有HttpGet方法遵循一个类似的模式。他们获得电影对象(或对象的列表,在Index的情况下),并通过模型的视图。Create方法传递一个空的电影对象来创建视图。所有的方法创建、编辑、删除或者修改数据HttpPost过载的方法。修改数据在一个HTTP GET方法是一个安全风险,如博客条目所述 ASP.NET MVC Tip #46 – Don’t use Delete Links because they create Security Holes,因为他们创造了安全漏洞。修改数据获得方法也违反了HTTP的最佳实践和其他建筑模式,它指定,GET请求不应改变应用程序的状态。换句话说,执行一个GET操作应该是一个安全的操作,没有副作用,不会修改您保存数据。



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值