本节内容:

  • 向 Movie 模型添加了验证逻辑。
  • 确保每当用户创建或编辑电影时,都会强制执行验证规则。

坚持 DRY 原则

这可以减少所需编写的代码量,并使编写的代码更少出错,更易于测试和维护。

可以在一个位置(模型类中)以声明方式指定验证规则,并且在应用中的所有位置强制执行。

将验证规则添加到电影模型

DataAnnotations 还包含 DataType 等格式特性,有助于格式设置但不提供任何验证。

更新 Movie 类以使用内置的 RequiredStringLengthRegularExpression 和 Range 验证特性。

public class Movie
{
    public int Id { get; set; }
 
    [StringLength(60, MinimumLength = 3)]
    [Required]
    public string Title { get; set; }
 
    [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }
 
    [Range(1, 100)]
    [DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }
 
    [RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$")]
    [Required]
    [StringLength(30)]
    public string Genre { get; set; }
 
    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
    [StringLength(5)]
    [Required]
    public string Rating { get; set; }
}

 

验证特性指定要对应用这些特性的模型属性强制执行的行为:

  • Required 和 MinimumLength 特性表示属性必须有值;但用户可输入空格来满足此验证。

  • 在上述代码中,即“Genre”(分类):

    • 只能使用字母。
    • 不允许使用空格、数字和特殊字符。
  • RegularExpression“Rating”(分级):

    • 要求第一个字符为大写字母。
    • “PG-13”对“分级”有效,但对于“分类”无效。
  • Range 特性将值限制在指定范围内。

  • StringLength 特性使你能够设置字符串属性的最大长度,以及可选的最小长度。

  • 从本质上来说,需要值类型(如 decimalintfloatDateTime),但不需要 [Required] 特性。

同时它能确保你无法忘记验证某些内容,并防止你无意中将错误数据导入数据库。

验证错误 UI

运行应用并导航到电影控制器。

当 jQuery 客户端验证检测到错误时,会显示一条错误消息。

ASP.NET Core3.1 MVC 添加验证规则

备注

请参阅 GitHub 问题 4076。

客户端(使用 JavaScript 和 jQuery)和服务器端(若用户禁用 JavaScript)都必定会遇到这些错误。

使用 Edit 操作方法测试验证后,即已应用相同的验证。

F12 开发人员工具在 HTTP Post 方法中设置断点来对此进行验证。

验证工作原理

下列代码显示两种 Create 方法。

// GET: Movies/Create
public IActionResult Create()
{
    return View();
}
 
// POST: Movies/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
    [Bind("ID,Title,ReleaseDate,Genre,Price, Rating")] Movie movie)
{
    if (ModelState.IsValid)
    {
        _context.Add(movie);
        await _context.SaveChangesAsync();
        return RedirectToAction("Index");
    }
    return View(movie);
}

 

如果在浏览器中禁用 JavaScript,客户端验证将被禁用,而你可以测试 HTTP POST Create 方法 ModelState.IsValid 检测任何验证错误。

在没有 JavaScript 的情况下仍然可以进行完整的验证。

以下图片显示如何在 FireFox 浏览器中禁用 JavaScript。

ASP.NET Core3.1 MVC 添加验证规则

以下图片显示如何在 Chrome 浏览器中禁用 JavaScript。

ASP.NET Core3.1 MVC 添加验证规则

禁用 JavaScript 后,发布无效数据并单步执行调试程序。

ASP.NET Core3.1 MVC 添加验证规则

Create.cshtml 视图模板的一部分在以下标记中显示 :

<h4>Movie</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>          
        
        @*Markup removed for brevity.*@

 

操作方法使用上述标记来显示初始表单,并在发生错误时重新显示此表单。

验证。

这些相同的验证规则自动应用于 Edit 视图和可能创建用于编辑模型的任何其他视图模板。

这意味着对 DRY 原则的完全遵守。

使用 DataType 特性

以下代码显示具有适当 DataType 特性的 ReleaseDate 和 Price 属性。

[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
 
[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }

 

DataType 特性不提供任何验证 。

默认情况下,数据字段根据基于服务器的 CultureInfo 的默认格式进行显示。

DisplayFormat 特性用于显式指定日期格式:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

 

(你可能不想为某些字段执行此操作 — 例如对于货币值,你可能不希望文本框中的货币符号可编辑。)

DataType 特性传达数据的语义而不是传达如何在屏幕上呈现数据,并提供 DisplayFormat 不具备的以下优势:

  • 浏览器可启用 HTML5 功能(例如显示日历控件、区域设置适用的货币符号、电子邮件链接等)

  • 默认情况下,浏览器将根据区域设置采用正确的格式呈现数据。

  • DataType 特性使 MVC 能够选择正确的字段模板来呈现数据(如果 DisplayFormat 由自身使用,则使用的是字符串模板)。

备注

例如,以下代码将始终显示客户端验证错误,即便日期在指定的范围内:

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

通常,在模型中编译固定日期是不恰当的,因此不推荐使用 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)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }
 
    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
    public string Rating { get; set; }
}

 

在本系列的下一部分中,我们将回顾应用,并对自动生成的 Details 和 Delete 方法进行一些改进。

其他资源

相关文章:

  • 2021-11-01
  • 2022-02-27
  • 2021-08-09
  • 2022-12-23
  • 2021-10-09
猜你喜欢
  • 2022-12-23
  • 2021-04-15
  • 2021-12-11
  • 2022-01-05
  • 2021-12-12
相关资源
相似解决方案