There can be no Triumph without Loss,No Victory without Suffering,No Freedom without Sacrifice.
All you have to decide is what to do with the time that is given to you.
Get busy Living, or Get busy Dying?
  首页 | 留言给我 | 订阅 Rss | CLI | 黄白之恋 Posts:158   Hits: 5545893    Comments: 173    
 日历归档
<<  <  2024 - 11  >  >>
SuMoTuWeThFrSa
     12
3456789
10111213141516
17181920212223
24252627282930
 About Me
 Name: ZhangSichu
 Sex: Male
 Age: 32
 Email: ZhangSichu@gmail.com
 MSN: ZhangSichu@hotmail.com
 Home: ZhangSichu.com
 WeiBo: weibo.com/zhangsichu
 个人推荐
 分类归档
  ·C++/C(5)  RSS
  ·软件工程(1)  RSS
  ·杂事/随感(26)  RSS
  ·.Net/Java(30)  RSS
  ·面向对象程序设计(5)  RSS
  ·汇编/破解(0)  RSS
  ·平面设计(3)  RSS
  ·SQL(5)  RSS
  ·COM/COM+(2)  RSS
  ·Web开发(81)  RSS
 My Friends
Back Forward Refresh Home 2024年11月23日 星期六 RSS CLI Mine Sweeper. In Javascript.

  [翻译] ASP.NET MVC 5 系列教程 [七] 添加校验方法
字体大小 [ ]

原文地址: http://www.asp.net/mvc/overview/getting-started/introduction/examining-the-edit-methods-and-edit-view

在本节中,您将验证电影控制器生成的编辑方法(Edit action methods)和视图。但是首先将修改点代码,使得发布日期属性(ReleaseDate)看上去更好。打开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; }


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

在浏览器地址栏里追加/Movies, 浏览到Movies页面。并进入编辑(Edit)页面。
Click to Open in New Window

Edit(编辑)链接是由Views\Movies\Index.cshtml视图中的Html.ActionLink方法所生成的:
@Html.ActionLink("Edit", "Edit", new { id=item.ID })

Click to Open in New Window

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

在上图中所生成的链接是http://localhost:xxxxx/Movies/Edit/4。默认的路由 (在App_Start\RouteConfig.cs 中设定) 使用的 URL 匹配模式为: {controller}/{action}/{id}。因此,ASP.NET 将http://localhost:xxxxx/Movies/Edit/4转化到Movies 控制器中Edit操作方法,参数ID等于 4 的请求。查看App_Start\RouteConfig.cs文件中的以下代码。

MapRoute方法是使用HTTP请求路由查找到正确的控制器(controller)和行动方法,并提供了可选ID的参数。MapRoute方法也被用于通过HtmlHelpers如ActionLink的控制器,操作方法及任何路由数据,以生成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 }
);
}


您还可以使用QueryString来传递操作方法的参数。例如,URL: http://localhost:xxxxx/Movies/Edit?ID=3还会将参数ID为 3的请求传递给Movies控制器的Edit操作方法。
Click to Open in New Window

打开Movies控制器。如下所示的两个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);
}


注意,第二个Edit操作方法的上面有HttpPost属性。此属性指定了Edit方法的重载,此方法仅被POST 请求所调用。您可以将HttpGet属性应用于第一个编辑方法,但这是不必要的,因为它是默认的属性。(操作方法会被隐式的指定为HttpGet属性,从而作为HttpGet方法。) 绑定(Bind)属性是另一个重要安全机制,可以防止黑客攻击(从over-posting数据到你的模型)。您应该只包含在bind属性属性,您想要更改。您可以阅读有关在我overposting security note。我们将在本教程中使用的简单模型,模型中绑定所有数据。ValidateAntiForgeryToken属性是用来防止伪造的请求,并配对@Html.AntiForgeryToken()文件 (Views\Movies\Edit.cshtml),如下图所示,部分在编辑view文件:
@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() 生成隐藏的窗体, 防伪令牌必须匹配的的Movies控制器的Edit方法。在我的教程XSRF/CSRF Prevention in MVC,你可以读到更多关于跨站点请求伪造(也称为XSRF或CSRF)。

HttpGet Edit方法会获取电影ID参数、 查找影片使用Entity Framework 的Find方法,并返回到选定影片的编辑视图。如果不带参数调用Edit 方法,ID 参数被指定为默认值 零。如果找不到一部电影,则返回HttpNotFound 。当scaffolding自动创建编辑视图时,它会查看Movie类并为类的每个属性创建用于Render的<label>和<input>的元素。下面的示例为visual studio scaffolding自动创建的编辑视图:
@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.Movie 的声明,这将指定视图期望的模型类型为Movie。

scaffolded自动生成的代码,使用了Helper方法的几种简化的 HTML 标记。 Html.LabelFor 用来显示字段的名称("Title"、"ReleaseDate"、"Genre"或"Price")。 Html.EditorFor 用来呈现 HTML <input>元素。Html.ValidationMessageFor 用来显示与该属性相关联的任何验证消息。

运行该应用程序,然后浏览URL,/Movies。单击Edit链接。在浏览器中查看页面源代码。HTML Form中的元素如下所示:

<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>


被<form> HTML 元素所包括的 <input> 元素会被发送到,<form>的action属性所设置的URL:/Movies/Edit。单击Save按钮时,from数据将会被发送到服务器。第二行显示隐藏XSRF通过@Html.AntiForgeryToken()调用生成的令牌。

处理 POST 请求
下面的代码显示了Edit操作方法的HttpPost处理:
[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);
}


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

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

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

如果您的电脑是是US-English的语言设置,可以跳过这一节,直接进入下一个教程。

注意,为了使jQuery支持使用逗号的非英语区域的验证 ,需要设置逗号(",")来表示小数点,你需要引入globalize.js并且你还需要具体的指定cultures/globalize.cultures.js文件 (地址在https://github.com/jquery/globalize) 在 JavaScript 中可以使用 Globalize.parseFloat。你可以从NuGet中安装非英语的jQuery的验证、插件。 (如果您使用的是英语语言环境,不要安装全球化 (Globalize)。)

1. 在工具(Tools)菜单,点击库程序包管理器( Library Package Manager),选择解决方案程序包管理器(Manage NuGet Packages for Solution).
Click to Open in New Window

2. 在左边面板上,选择联机库(Online,见下图)

3. 在搜索已安装库( Search Installed packages ),输入 Globalize搜索
Click to Open in New Window

点击安装(Install). JavaScript脚本 \jquery.globalize\globalize.js 文件将会添加到您的当前工程下. 脚本\jquery.globalize\cultures\ 文件夹的下面会包含很多不同文化的JavaScript文件

注意事项:安装这个包,预计花费5分钟时间(取决于您的网速).

下面的代码展示了在"FR-FR" Culture下的 Views\Movies\Edit.cshtml 视图:
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")

<script src="~/Scripts/globalize/globalize.js"></script>
<script src="~/Scripts/globalize/cultures/globalize.culture.@(System.Threading.Thread.CurrentThread.CurrentCulture.Name).js"></script>
<script>
$.validator.methods.number = function (value, element) {
return this.optional(element) ||
!isNaN(Globalize.parseFloat(value));
}
$(document).ready(function () {
Globalize.culture(@(System.Threading.Thread.CurrentThread.CurrentCulture.Name));
});
</script>
<script>
jQuery.extend(jQuery.validator.methods, {
range: function (value, element, param) {
//Use the Globalization plugin to parse the value
var val = Globalize.parseFloat(value);
return this.optional(element) || (
val >= param[0] && val <= param[1]);
}
});
$.validator.methods.date = function (value, element) {
return this.optional(element) ||
Globalize.parseDate(value) ||
Globalize.parseDate(value, "yyyy-MM-dd");
}
</script>
}


为了避免在每一个编辑视图重复这段代码,你可以将它移动到布局文件。要优化脚本下载,看我的教程Bundling and Minification。欲了解更多信息,请,ASP.NET MVC 3 Internationalization和ASP.NET MVC 3 Internationalization - Part 2 (NerdDinner)。

作为一个临时解决办法,如果您不能验证当前的区域设置,可以强制你的计算机使用US English,或者你可以在浏览器中禁用JavaScript。为了强制您的电脑使用美国英语,你可以在项目根目录Web.config文件里面添加的全球化设置。

下面的代码演示设置为美国英语的全球化文化设置。
<system.web>
<globalization culture ="en-US" />
<!--elements removed for clarity-->
</system.web>


在接下来的教程,我们将实现搜索功能。
  Posted @ 5/3/2015 2:05:03 PM | Hits (16273) | Comment (0

  Post Comment
标题 *
作者 *
密码 记住我
评论 *
    


Stable in Firefox 1.5 2.0Stable in IE6 IE7Stable in MozillaStable in Netscape
ZhangSichu.com V0.1.7507
Powered By ZhangSichu
Copyright © ZhangSichu
Download ZhangSichu.com source code. Download source code