楠槡

ASP.NET MVC学习笔记06编辑方法和编辑视图

2017-05-20

上一篇中,说到了MVC生成的Index方法,和Details方法,现在来说一下自动生成的方法和视图,应该怎么的来进行编辑。

优化日期显示

在这之前,先对前面的代码进行优化,使得发布日期属性(ReleaseDate)看上去更好。打开Models/Movies.cs参考下图进行修改。

优化ReleaseData的显示

上图中用到了DataAnnotations。Display属性指明要显示的字段的名 称(在本例中“Release Date”来代替“ReleaseDate”)。DataType属性用于指定类型的数据,在本例它是一个日期,所以不会显示存放在该字段时间详情。DisplayFormat属性在Chrome浏览器里有一个bug:呈现的日期格式不正确。

调试,浏览,然后点击一个条目,进入编辑。

修改完善后的编辑页面

如上图所示,Edit(编辑)链接是由Views\ Movies\Index.cshtml 视图中Html.ActionLink方法所生成的.

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

Html对象是一个 Helper, 以属性的形式在System.Web.Mvc.WebViewPage基类上公开。ActionLink是一个帮助方法(Helper),便于动态生成指向Controller中操作方法 的HTML 超链接链接。ActionLink方法的第一个参数是想要呈现的链接文本 (例如,<a>Edit Me</a>)。第二个参数是要调用的操作方法的名称(在本例中, Edit方法)。最后一个参数是一个匿名对象 (anonymous object),用来生成路由数据 (在上图中,ID 为1 的)。

因此跳转的链接为,http://localhost:50948/movies/Edit/1,默认的路由 (在
App_Start\RouteConfig.cs中设定)使用的 URL 匹配模式为: {controller}/{action}/{id}。因 此,ASP.NET 将 http://localhost:xxxxx/Movies/Edit/4转化到 Movies 控制器中 Edit操作 方法,参数 ID等于1 的请求。所以,输入http://localhost:50948/movies/Edit?id=1同样会把参数ID 等于1的请求传给控制器的Edit方法。

控制器的Edit方法

再来看看MoviesController中的Edit的两个方法。
 MoviesController中的Edit两个方法

注意,第二个Edit操作方法的上面有HttpPost属性。此属性指定了Edit方法的重载,此方法仅 被POST 请求所调用。可以将HttpGet属性应用于第一个编辑方法,但不需要这样,因为它是默认的属性。(操作方法会被隐式的指定为HttpGet属性,从而作为 HttpGet 方法。) 绑定(Bind)属性是另一个重要安全机制,可以防止黑客攻击(从over-posting数据到模型)。应该只包含在bind属性属性,本教程中使用的简单模型,模型中绑定所有数据。ValidateAntiForgeryToken属性是用来防止伪造的请求,并配对@Html.AntiForgeryToken()文件 ( Views\Movies\Edit.cshtml ),如下图所示,部分在Edit View文件:
 Edit View内容
@Html.AntiForgeryToken() 生成隐藏的窗体, 防伪令牌必须匹配Movies控制器的 Edit 方法。在教程 XSRF/CSRF Prevention in MVC,你可以读到更多关于跨站点请求伪造 (也称为XSRF或CSRF)。
HttpGet Edit方法会获取电影ID参数、 查找影片使用 Entity Framework 的Find 方法,并返回 到选定影片的编辑视图。如果不带参数调用Edit 方法,ID 参数被指定为默认值 零。如果找不到一 部电影,则返回 HttpNotFound 。当 scaffolding自动创建编辑视图时,它会查看Movie类并为 类的每个属性创建用于 Render的<label><input>的元素。

注意,视图模板在文件的顶部有 @model MvcMovie.Models.Movie的声明,这将指定视 图期望的模型类型为` Movie。

scaffolded自动生成的代码,使用了Helper 方法的几种简化的 HTML 标记 。Html.LabelFor 用来显示字段的名称(”Title”、”ReleaseDate”、”Genre”或”Price”)。Html.EditorFor用来呈现 HTML <input>元素。Html.ValidationMessageFor用来 显示与该属性相关联的任何验证消息。视图模板在文件的顶部有 @model MvcMovie.Models.Movie的声明,这将指定视 图期望的模型类型为 Movie。
Edit页面的HTML内容的From信息

处理 POST 请求

回看前面的Eidt的Post方法。

ASP.NET MVC model binder接收form所post的数据,并转换所接收的 Movie请求数据从而创建一个Movie对象。ModelState.IsValid方法用于验证提交的表单数据是否可用于修改(编辑或更新)一个Movie对象。如果数据是有效的电影数据,将保存到数据库的Movies集合(MovieDBContext 实例)。通过调用MovieDBContext的SaveChanges方法,新的电影数据会被保存到数据库。数据保存之后,代码会把用户重定向到 MoviesController类的Index操作方法,页面将显示电影列表,同时包括刚刚所做的更新。

一旦客户端验证确定某个字段的值是无效的,将显示出现错误消息。如果禁用 JavaScript,则不会有客户端验证,但服务器将检测回传的值是无效的,而且将重新显示 表单中的值与错误消息。在本教程的后面,我们验证更详细的审查。 Edit.cshtml 视图模板 中的 Html.ValidationMessageFor Helper将用来显示相应的错误消息。

所有 HttpGet方法遵循类似的模式。他们得到一个电影对象(或对象列表中,如本案例的 Index),并把模型数据传递给视图。Create方法传递一个空的影片对象给Create视图。 所有的 create, edit, delete方法,或其他的方法: 用HttpPost重载的方法修改数据。修改 数据在HTTP GET方法, 存在安全风险。在HTTP GET方法中修改数据也违反HTTP 的最佳实践和REST模式架构,指明GET请求不应该改变你的应用程序的状态。换句话说,执行GET操作应该是一个安全,操作,无任何副作用,不会修改你的持久化数据。

按照电影流派添加搜索

首先,如果之前添加了 HttpPost 的Index方法,请立即删除它。

下面,通过一些列的修改,来让用户可以通过流派来搜索电影。先从Controller中的index方法开始。

修改Index方法实现搜索功能

这个版本的 Index方法将接受一个附加的 movieGenre参数。前几行的代码会创建一个 List对象来保存数据库中的电影流派。

下面的代码是从数据库中检索所有流派的 LINQ 查询:

1
2
3
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;

该代码使用泛型 List集合的 AddRange方法将所有不同的流派,添加到集合中的。(使 用 Distinct修饰符,不会添加重复的流派 – 例如,在我们的示例中添加了两次喜剧)。

该代码然后在ViewBag对象中存储了流派的数据列表。的SelectList对象在ViewBag作 为存储类数据(这样的电影流派),然后在下拉列表框中的数据访问类别,是一个典型的MVC applications的方法。
下面的代码演示如何检查 movieGenre参数。如果它不是空的,代码进一步指定了所查询的电影流派。

1
2
3
4
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}

如前所述,查询数据不会在数据库上运行,直到电影列表迭代结束(恰发生在View, Index方法返回后)。

注意:这个地方用到了LinQ的知识,如果对LinQ不太了解的,可以查阅官方文档.

Index视图添加标记

Views\Movies\Index.cshtml文件中,添加Html.DropDownList辅助方法,在TextBox前。完成的代码如下图所示:
修改Index视图

下面的代码:

1
@Html.DropDownList("movieGenre", "All")

ViewBag中,”movieGenre“ 参考作为key在DropDownList中搜索 IEnumerable<SelectListItem > .

ViewBag填入的操作方法:
参数“All”提供的项列表中的预先选择的。如我们使用下面的代码:

1
@Html.DropDownList("movieGenre", "Comedy")

在我们的数据库中,我们拥有与“喜剧”流派的电影,“喜剧”在下拉列表中将预先选 择。因为我们没有一个电影流派“All”,也没有“All”的 SelectList,所以当我们post back后不做任何选择,movieGenre查询字符串值是空的。
运行应用程序并浏览 /Movies/Index。尝试搜索流派,来检索信息。

根据Genre流派检索数据

在本篇中,创建了一个搜索的方法和视图,使用它,用户可以通过电影标题和流派来搜 索。在下一篇中,将看到如何添加一个属性到 Movie model,和如何添加一个初始值设定项值,它会自动创建一个测试数据库。

Tags: dotNET
使用支付宝打赏
使用微信打赏

若你觉得我的文章对您有帮助,点击上方按钮请我喝杯咖啡☕

若文章中存在问题,或您有任何意见和疑问,均可与我联系

扫描二维码,分享此文章 📱