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

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

优化日期显示

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

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

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

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

@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的两个方法。

注意,第二个Edit操作方法的上面有HttpPost属性。此属性指定了Edit方法的重载,此方法仅 被POST 请求所调用。可以将HttpGet属性应用于第一个编辑方法,但不需要这样,因为它是默认的属性。(操作方法会被隐式的指定为HttpGet属性,从而作为 HttpGet 方法。) 绑定(Bind)属性是另一个重要安全机制,可以防止黑客攻击(从over-posting数据到模型)。应该只包含在bind属性属性,本教程中使用的简单模型,模型中绑定所有数据。ValidateAntiForgeryToken属性是用来防止伪造的请求,并配对@Html.AntiForgeryToken()文件 ( Views\Movies\Edit.cshtml ),如下图所示,部分在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。

处理 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方法将接受一个附加的 movieGenre参数。前几行的代码会创建一个 List对象来保存数据库中的电影流派。

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

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

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

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

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

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

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

Index视图添加标记

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

下面的代码:

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

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

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

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

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

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏张善友的专栏

[翻译]开发Silverlight 2.0的自定义控件

原文:Developing a Custom Control for Silverlight 2.0 译者:张善友 Download MediaButto...

1939
来自专栏salesforce零基础学习

salesforce零基础学习(八十四)配置篇: 自定义你的home page layout

当我们进入salesforce系统或者切换app后,默认第一个看到的就是home页面。home页面简单的来说可以包括左侧(narrow component)和右...

3095
来自专栏偏前端工程师的驿站

.NET魔法堂:工程构建基石->MSBuild

一、前言                               MSBuild是一个既熟悉又陌生的名字,Visual Studio的项目加载和构建均通过M...

2868
来自专栏Windows Community

Windows Phone 8.1 新特性 - 页面导航

本篇介绍一下Windows Phone 8.1 中页面导航的实现方式。 大家对Windows Phone 8 中页面导航的实现一定不陌生,我们使用 Naviga...

3217
来自专栏xingoo, 一个梦想做发明家的程序员

Nodejs·内存控制

之前有考虑过Node中的内存管理,但是没想到Node的内存机制与JVM如此相像。 看完这部分的内容,基本可以了解Node中的内存使用技巧: 1 尽量不要做...

1927
来自专栏Java帮帮-微信公众号-技术文章全总结

POI导入导出【面试+工作】

POI导入导出【面试+工作】 1.场景一 近期项目中的excel导入导出功能需求频繁的出现,趁此机会,今天笔者对POI的Excel数据的导入导出做一...

3144
来自专栏我杨某人的青春满是悔恨

Swift纯代码页面传值

页面跳转啊页面间传值啊,这是每个项目几乎都要用到的东西。近年来苹果一直都在推Storyboard,页面跳转可以直接在Storyboard上拉线,然后用segue...

902
来自专栏开源优测

JMeter断言07

前言 在jmeter中断言用于验证服务器返回的数据是否满足我们的要求。 jmeter提供了以下断言类型: ? 下面我们主要对响应断言、XPath Asserti...

3567
来自专栏解Bug之路

Druid连接管理分析

        Druid有且只有一个线程来创建连接,为了防止不必要的线程时间片的消耗,其采用了await()/notify()的方式,当其创建了足够的多的连接...

1092
来自专栏有趣的Python

5- vue django restful framework 打造生鲜超市 -完成商品列表页(上)

使用Python3.6与Django2.0.2(Django-rest-framework)以及前端vue开发的前后端分离的商城网站 项目支持支付宝支付(...

4216

扫码关注云+社区