ASP.NET Core 中文文档 第二章 指南(4.9)添加验证
原文:Adding Validation
作者:Rick Anderson
翻译:谢炀(Kiler)
校对:孟帅洋(书缘)、娄宇(Lyrics)、许登洋(Seay)
在本章节中你将为 Movie 模型类添加验证逻辑,以确保用户在试图创建或编辑影片数据时强制执行验证规则。
保持DRY原则
ASP.NET MVC 的核心原则之一是 DRY (“不要重复自己”)。ASP.NET MVC 鼓励你只指定一次行为或者功能,然后可以在应用程序里面到处使用,这样大大的减少了需要编写的代码量,并且使你编写不容易出错,更容易测试,以及更容易维护的代码。
ASP.NET MVC 和 Entity Framework Core Code First 中的验证功能,是 DRY 原则实际应用的一个很好的实例。你可以在某个位置(模型类)声明指定方式的验证规则,验证规则可以在整个应用程序中生效。
让我们来看看如何在电影应用程序中利用验证功能。
向 Movie 模型中添加验证规则
打开 Movie.cs 文件。DataAnnotations 提供了一组内置的验证特性,你可以对任何类或属性应用。(它也同时包含了一些格式化特性,比如 DataType 用来帮你格式化数据而非提供验证功能。)
现在修改 Movie 类,利用内置的 Required 、 StringLength 、RegularExpression 以及 Range 验证特性。
public class Movie
{
public int ID { get; set; }
[StringLength(60, MinimumLength = 3)] //手工高亮
public string Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")] //手工高亮
[Required] //手工高亮
[StringLength(30)] //手工高亮
public string Genre { get; set; }
[Range(1, 100)] //手工高亮
[DataType(DataType.Currency)] //手工高亮
public decimal Price { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")] //手工高亮
[StringLength(5)] //手工高亮
public string Rating { get; set; }
}
验证特性指定了你想要应用到模型属性上的验证行为。Required 以及 MinimumLength 特性表示属性不能为空,但无法阻止用户用填写空格的方式来满足此验证条件。RegularExpression 特性用来限制用户输入的文字类型。 在上面的例子中,Genre 以及 Rating 只能输入字母(不允许输入空格、数字以及特殊字符)。Range 特性限制值在指定的范围内。StringLength 特性可让你设定字符串最大长度,以及最小长度(可选)。值类型(如decimal, int, float, DateTime) 本身是必须的,并不需要 [Required] 特性。
ASP.NET 自动执行的验证规则将有助于使你的应用程序更加健壮。它还确保提醒你不要忘记验证数据,让非法数据进入到数据库中。
MVC 中的验证错误 UI
运行程序并导航到 Movies controller。
点击 Create New 链接创建一个新的 Movie。在表单中填写一些无效的数据,jQuery 客户端验证马上就会发现错误,立刻呈现到界面上。

注意
你也许无法在Price字段中输入小数点或者逗号。为了让 jQuery validation 支持非英语环境使用逗号(",")代替小数点,以及非美式英语日期格式,你必须采取措施国际化你的应用程序。参考 附录资源 获取更多信息。 现在仅仅输入整数,比如 10。
请注意,表单在包含无效值的每个字段下自动呈现一个适当的验证错误消息。错误包括客户端(使用 JavaScript 和 jQuery )和服务器端(以防用户已禁用 JavaScript)。
一个显而易见的好处是,你并不需要改变 MoviesController 类或者 Create.cshtml 视图中的一行代码,就可以实现验证界面。你在本教程前面创建的控制器和视图,自动使用你指定的 Movie 模型类的属性上的验证特性的验证规则。使用 Edit 操作方法测试验证,(与Create 方法)同样的验证生效。
表单数据不会被发送到服务器直到没有客户端验证错误。你可以在 HTTP Post 方法中设置断点,并通过使用 Fiddler 工具或者 F12 开发者工具 访问这个方法来验证这一点。
创建视图和创建方法中如何触发验证
也许你会好奇生成的控制器或视图中的代码没有任何更新的情况下验证界面是如何产生的。下一个清单显示的是两个 Create 方法。
// GET: Movies/Create
public IActionResult Create()
{
return View();
}
// POST: Movies/Create
// 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 async Task<IActionResult> Create([Bind("ID,Genre,Price,ReleaseDate,Title,Rating")] Movie movie)
{
if (ModelState.IsValid)
{
_context.Add(movie);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(movie);
}
第一个(HTTP GET) Create 的操作方法显示初始创建表单。第二个([HttpPost])版本的操作方法负责处理 post 请求。第二个 Create 的方法(HttpPost 版本)调用 ModelState.IsValid 检查是否有任何验证错误。调用该方法将检查任何已应用到对象属性上的验证。如果对象的 Create 方法验证错误,重新显示表单。如果没有错误,该方法在数据库中保存新的 movie。在我们的 movie 例子中,在客户端验证检测到错误时,表单将不会发送到服务器,第二个 Create 方法不会被调用。如果你的浏览器禁用了 JavaScript,客户端验证被禁用,HTTP POST 版本的 Create 方法调用 ModelState.IsValid,以检查是否存在任何验证错误。
你可以在 [HttpPost] Create 方法中设置一个断点,用来验证该方法不会被调用,客户端验证发现错误时将不提交表单数据。如果你的浏览器禁用了 JavaScript ,然后提交有错误的表单,断点会被命中。不支持 JavaScript 的情况下,你仍然可以得到充分验证。下面的图片展示了如何在 IE 浏览器中禁用 JavaScript 脚本。

下面的图片展示了如何在 FireFox 浏览器中禁用 JavaScript 脚本。

下面的图片展示了如何在 Chrome 浏览器中禁用 JavaScript 脚本。

在禁用 JavaScript 脚本之后,post 非法数据并在调试器中单步调试。

下面是你在本教程前面用基架生成的 Create.cshtml 视图模板的一部分。它使用上面展示的两种 action 方法来显示初始表单并且在发生错误时重新显示。
<form asp-action="Create">
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Genre" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Genre" class="form-control" /> <!--手工高亮-->
<span asp-validation-for="Genre" class="text-danger" /> <!--手工高亮-->
</div>
</div>
@*Markup removed for brevity.*@ <!--手工高亮-->
<div class="form-group">
<label asp-for="Rating" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Rating" class="form-control" /> <!--手工高亮-->
<span asp-validation-for="Rating" class="text-danger" /> <!--手工高亮-->
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
</form>
Input Tag Helper 消费 DataAnnotations 特性和产生jQuery验证所需要在客户端生成的 HTML 属性。Validation Tag Helper 负责显示错误信息。更多请参考 Validation 。
非常棒的是控制器和 Create 视图模板不知道实际执行的验证规则或显示的具体错误消息。只需要在 Movie 类里指定验证规则和错误字符串,同样的验证规则会自动应用到 Edit 视图和任何其他视图模板,你可以创建、编辑你的模型。
如果你想更改验证逻辑,你可以限定在一处地方(在本例中,是指 Movie 类),为模型添加验证特性。你不需要担心应用程序的不同部分执行的规则不一致 —— 所有的验证逻辑在同一个地方定义然后在各处使用 。这样可以使得代码很干净,而且易于维护和改进。这意味着,你充分遵循了 DRY 原则。
使用 DataType 特性
打开 Movie.cs 文件,并查看 Movie 类。System.ComponentModel.DataAnnotations 命名空间提供了除了内置的验证特性以外的一套格式化特性。我们已经应用了 DataType 枚举值到发布日期和价格字段。下面的代码显示了 ReleaseDate 和 Price 字段如何使用 DataType 特性。
[Display(Name = "Release Date")]
[DataType(DataType.Date)] //手工高亮
public DateTime ReleaseDate { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)] //手工高亮
public decimal Price { get; set; }
DataType 特性只用于视图引擎对数据进行格式化(或者提供给诸如 <A> 标签 的Url或者 <a href="mailto:EmailAddress.com"> 提供的电子邮件),你可以使用 RegularExpression 特性来验证数据的格式,DataType 特性用于指定比数据库的自带类型更为具体的数据类型,它们不是验证特性,在本示例中我们只想跟踪日期,而不需要具体时间。在 DataType 枚举提供了许多数据类型,如日期、时间、手机号码、货币、电子邮件地址等。DataType 特性一样可以让应用程序具备自动提供特定数据类型的功能。例如,一个 mailto: 链接可以使用 DataType.EmailAddress 数据类型创建,在支持 Html5 的浏览器中并且日期选择器可以提供 DataType.Date 的值。DataType 特性向浏览器发送 HTML 5 标签 data- (pronounced data dash)。DataType 特性 无法 提供任何验证。
DataType.Date 不指定日期的显示格式。默认情况下,数据字段默认的显示格式基于服务器的 CultureInfo 设置来决定的。
DisplayFormat 特性被用来格式化日期:
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }
ApplyFormatInEditMode 用来指定格式是否应用到文本框编辑。(你可能不希望在某些字段中使用这个功能——例如,对于货币值,你可能不希望在文本框中对货币符号进行编辑。)
你可以直接使用 DisplayFormat 特性本身,但是更好的方式是建议使用 DataType , DataType 特性仅仅传递数据的语义,并不会通知浏览器如何呈现,如果不使用 DisplayFormat 有以下好处:
- 浏览器可以启用 HTML5 功能(例如显示日历控件,设置本地化的货币符号,电子邮件中的链接,等等)。
- 默认情况下,浏览器将基于你的 本地环境 使用正确的格式渲染数据。
DataType特性可以使 MVC 选择正确的字段模板来呈现数据(比如DisplayFormat如果单独使用 string 模板)。更多信息,请参考 Brad Wilson 的 ASP.NET MVC 2 模版。(尽管是为 MVC 2编写的, 文章依然适用于当前的 ASP.NET MVC 版本。)
注意
当Range特性同时使用DateTime类型的时候 jQuery 验证无法生效。例如,下面的代码将始终显示客户端验证错误,即使日期在指定范围内:
[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]
你需要禁止在 DateTime 上使用 Range 特性来进行 JQuery 日期验证。在你的模型中编译具体日期通常不是一个好的做法,所以不建议在 Range 特性中使用 DateTime。
下面的代码展示了如何将各种验证特性合并在一行显示:
public class Movie
{
public int ID { get; set; }
[StringLength(60, MinimumLength = 3)] //手工高亮
public string Title { get; set; }
[Display(Name = "Release Date"), DataType(DataType.Date)] //手工高亮
public DateTime ReleaseDate { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$"), Required, StringLength(30)] //手工高亮
public string Genre { get; set; }
[Range(1, 100), DataType(DataType.Currency)] //手工高亮
public decimal Price { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$"), StringLength(5)] //手工高亮
public string Rating { get; set; }
}
在下一个系列里面, 我们会重新审视应用程序,为自动生成的 Details 以及 Delete 方法做一些提升。
附录资源
ASP.NET Core 中文文档 第二章 指南(4.9)添加验证的更多相关文章
- ASP.NET Core 中文文档 第二章 指南(4.6)Controller 方法与视图
原文:Controller methods and views 作者:Rick Anderson 翻译:谢炀(Kiler) 校对:孟帅洋(书缘) .张仁建(第二年.夏) .许登洋(Seay) .姚阿勇 ...
- ASP.NET Core 中文文档 第二章 指南(4.4)添加 Model
原文:Adding a model 作者:Rick Anderson 翻译:娄宇(Lyrics) 校对:许登洋(Seay).孟帅洋(书缘).姚阿勇(Mr.Yao).夏申斌 在这一节里,你将添加一些类来 ...
- ASP.NET Core 中文文档 第二章 指南 (09) 使用 Swagger 生成 ASP.NET Web API 在线帮助测试文档
原文:ASP.NET Web API Help Pages using Swagger 作者:Shayne Boyer 翻译:谢炀(kiler) 翻译:许登洋(Seay) 对于开发人员来说,构建一个消 ...
- ASP.NET Core 中文文档 第二章 指南(1)用 Visual Studio Code 在 macOS 上创建首个 ASP.NET Core 应用程序
原文:Your First ASP.NET Core Application on a Mac Using Visual Studio Code 作者:Daniel Roth.Steve Smith ...
- ASP.NET Core 中文文档 第二章 指南(2)用 Visual Studio 和 ASP.NET Core MVC 创建首个 Web API
原文:Building Your First Web API with ASP.NET Core MVC and Visual Studio 作者:Mike Wasson 和 Rick Anderso ...
- ASP.NET Core 中文文档 第二章 指南(3)用 Visual Studio 发布一个 Azure 云 Web 应用程序
原文:Getting Started 作者:Rick Anderson 翻译:谢炀(Kiler) 校对:孟帅洋(书缘).刘怡(AlexLEWIS).何镇汐 设置开发环境 安装最新版本的 Azure S ...
- ASP.NET Core 中文文档 第二章 指南(4.1)ASP.NET Core MVC 与 Visual Studio 入门
原文:Getting started with ASP.NET Core MVC and Visual Studio 作者:Rick Anderson 翻译:娄宇(Lyrics) 校对:刘怡(Alex ...
- ASP.NET Core 中文文档 第二章 指南(4.5)使用 SQL Server LocalDB
原文:Working with SQL Server LocalDB 作者:Rick Anderson 翻译: 魏美娟(初见) 校对: 孟帅洋(书缘).张硕(Apple).许登洋(Seay) Appl ...
- ASP.NET Core 中文文档 第二章 指南(5) 在 Nano Server 上运行ASP.NET Core
原文 ASP.NET Core on Nano Server 作者 Sourabh Shirhatti 翻译 娄宇(Lyrics) 校对 刘怡(AlexLEWIS).许登洋(Seay).谢炀(kile ...
随机推荐
- JAVA语言中的修饰符
JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...
- Webstorm+Webpack+echarts构建个性化定制的数据可视化图表&&两个echarts详细教程(柱状图,南丁格尔图)
Webstorm+Webpack+echarts ECharts 特性介绍 ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(I ...
- C# Excel导入、导出【源码下载】
本篇主要介绍C#的Excel导入.导出. 目录 1. 介绍:描述第三方类库NPOI以及Excel结构 2. Excel导入:介绍C#如何调用NPOI进行Excel导入,包含:流程图.NOPI以及C#代 ...
- 【原】AFNetworking源码阅读(五)
[原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...
- 如何进行python性能分析?
在分析python代码性能瓶颈,但又不想修改源代码的时候,ipython shell以及第三方库提供了很多扩展工具,可以不用在代码里面加上统计性能的装饰器,也能很方便直观的分析代码性能.下面以我自己实 ...
- redis 学习笔记(2)
redis-cluster 简介 redis-cluster是一个分布式.容错的redis实现,redis-cluster通过将各个单独的redis实例通过特定的协议连接到一起实现了分布式.集群化的目 ...
- 简约之美Jodd-http--深入源码理解http协议
Jodd 是一个开源的 Java 工具集, 包含一些实用的工具类和小型框架.简单,却很强大! jodd-http是一个轻巧的HTTP客户端.现在我们以一个简单的示例从源码层看看是如何实现的? Http ...
- cesium自定义气泡窗口infoWindow
一.自定义气泡窗口与cesium默认窗口效果对比: 1.cesium点击弹出气泡窗口显示的位置固定在地图的右上角,默认效果: 2.对于习惯arcgis或者openlayer气泡窗口样式的giser来说 ...
- 易用BPM时代,企业如何轻松驾驭H3?
众所周知,BPM作为企业发展的推动力,能敏捷高效的融合业务流程和信息资源.通过综合考虑流程的成本.效率.质量等方面因素,用IT系统将调整后的流程固化下来,从而降低企业管理成本,提高内部运营效率,提升企 ...
- BPM配置故事之案例3-参与者与数据自动加载
这才过了两天,阿海又来了. 阿海:公司决定改进管理方式,以后物资申请的申请人和申请部门要写具体使用人的名字和部门了. 小明:不是要让我改回去吧? 阿海:那太麻烦了,你能不能把申请人改成选择,选好人自动 ...