ASP.NET Core 中文文档 第二章 指南(4.9)添加验证

时间:2022-09-07 12:27:53

原文: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 类,利用内置的 RequiredStringLengthRegularExpression 以及 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 客户端验证马上就会发现错误,立刻呈现到界面上。

ASP.NET Core 中文文档 第二章 指南(4.9)添加验证

注意

你也许无法在 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 脚本。

ASP.NET Core 中文文档 第二章 指南(4.9)添加验证

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

ASP.NET Core 中文文档 第二章 指南(4.9)添加验证

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

ASP.NET Core 中文文档 第二章 指南(4.9)添加验证

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

ASP.NET Core 中文文档 第二章 指南(4.9)添加验证

下面是你在本教程前面用基架生成的 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 枚举值到发布日期和价格字段。下面的代码显示了 ReleaseDatePrice 字段如何使用 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 特性本身,但是更好的方式是建议使用 DataTypeDataType 特性仅仅传递数据的语义,并不会通知浏览器如何呈现,如果不使用 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)添加验证的更多相关文章

  1. ASP&period;NET Core 中文文档 第二章 指南(4&period;6)Controller 方法与视图

    原文:Controller methods and views 作者:Rick Anderson 翻译:谢炀(Kiler) 校对:孟帅洋(书缘) .张仁建(第二年.夏) .许登洋(Seay) .姚阿勇 ...

  2. ASP&period;NET Core 中文文档 第二章 指南(4&period;4)添加 Model

    原文:Adding a model 作者:Rick Anderson 翻译:娄宇(Lyrics) 校对:许登洋(Seay).孟帅洋(书缘).姚阿勇(Mr.Yao).夏申斌 在这一节里,你将添加一些类来 ...

  3. ASP&period;NET Core 中文文档 第二章 指南 (09) 使用 Swagger 生成 ASP&period;NET Web API 在线帮助测试文档

    原文:ASP.NET Web API Help Pages using Swagger 作者:Shayne Boyer 翻译:谢炀(kiler) 翻译:许登洋(Seay) 对于开发人员来说,构建一个消 ...

  4. ASP&period;NET Core 中文文档 第二章 指南(1)用 Visual Studio Code 在 macOS 上创建首个 ASP&period;NET Core 应用程序

    原文:Your First ASP.NET Core Application on a Mac Using Visual Studio Code 作者:Daniel Roth.Steve Smith ...

  5. ASP&period;NET Core 中文文档 第二章 指南(2)用 Visual Studio 和 ASP&period;NET Core MVC 创建首个 Web API

    原文:Building Your First Web API with ASP.NET Core MVC and Visual Studio 作者:Mike Wasson 和 Rick Anderso ...

  6. ASP&period;NET Core 中文文档 第二章 指南(3)用 Visual Studio 发布一个 Azure 云 Web 应用程序

    原文:Getting Started 作者:Rick Anderson 翻译:谢炀(Kiler) 校对:孟帅洋(书缘).刘怡(AlexLEWIS).何镇汐 设置开发环境 安装最新版本的 Azure S ...

  7. ASP&period;NET Core 中文文档 第二章 指南(4&period;1)ASP&period;NET Core MVC 与 Visual Studio 入门

    原文:Getting started with ASP.NET Core MVC and Visual Studio 作者:Rick Anderson 翻译:娄宇(Lyrics) 校对:刘怡(Alex ...

  8. ASP&period;NET Core 中文文档 第二章 指南(4&period;5)使用 SQL Server LocalDB

    原文:Working with SQL Server LocalDB 作者:Rick Anderson 翻译: 魏美娟(初见) 校对: 孟帅洋(书缘).张硕(Apple).许登洋(Seay) Appl ...

  9. ASP&period;NET Core 中文文档 第二章 指南(5) 在 Nano Server 上运行ASP&period;NET Core

    原文 ASP.NET Core on Nano Server 作者 Sourabh Shirhatti 翻译 娄宇(Lyrics) 校对 刘怡(AlexLEWIS).许登洋(Seay).谢炀(kile ...

随机推荐

  1. 网易免费&sol;付费163企业邮smtp服务器地址

    免费:smtp.ym.163.com 25/pop.ym.163.com 110 付费:smtp.qiye.163.com 25/pop.qiye.163.com 110

  2. 79&period; 212&period; Word Search &ast;HARD&ast; -- 字符矩阵中查找单词

    79. Word Search Given a 2D board and a word, find if the word exists in the grid. The word can be co ...

  3. 怎么给OCR文字识别软件设置正确的扫描分辨率

    ABBYY FineReader 12是一款专业的OCR文字识别软件,可快速方便地将扫描纸质文档.PDF文件和数码相机的图像转换成可编辑.可搜索的文本,不仅支持对页扫描,还支持多页扫描,扫描分辨率的选 ...

  4. 将项目添加到Finder侧边栏和工具栏

    转: http://www.cnblogs.com/wormday/archive/2011/05/08/2039468.html 1.在侧边栏和工具栏右键,有相应的设置选项 2.可以将项目拖到侧边栏 ...

  5. 今天在写powershell脚本中犯的两个错误

    可能是因为牙痛没睡好,今天老是犯错,还是脚本写错,特别难调. 第一个错误: powershell脚本里面,函数与函数互相调用的传参.其实就像调用普通的cmdlet一样的写法,应该这么写: Add-Sc ...

  6. VSCode插件MSSQL教程(昨天提了一下)

    推荐一个跨平台SQL IDE:https://docs.microsoft.com/zh-cn/sql/sql-operations-studio/download 什么数据库都木有(系统自带的不算) ...

  7. leaflet 学习备忘

    leaflet 开源js地图工具.非常好用. leaflet参考:http://leafletjs.com/ 特性: 完全开源,可以基于不同的第三方瓦片生成地图. 基于原始GPS,无需转换 可创建离线 ...

  8. CTFcracktools——非常实用的CTF解密工具

    做bugku的crypto题时偶然发现了这个,吐血推荐!! 十分全面好用 整合了常见的解码.进制转换等CTF常用的工具: 下载地址: https://github.com/0Linchen/CTFCr ...

  9. 当锚点定位遇上position&colon; fixed

    <!DOCTYPE html><html> <head> <title>当锚点定位遇上position: fixed</title> &lt ...

  10. gitlab--ci文件

    1.when: manual  手动执行(加到哪个脚本中,哪个就会变成手动执行)