1 Model级别错误消息
Model层错误消息被用到整个实体,而不是单个属性,我们只需要给AddModelError() 方法第一个参数中提供一个空值,如下代码:
ModelState.AddModelError("", "Some Model-Level error"); 采用一个例子,假如我们不想让名字为Osama Bin的这个人申请Job,为了实现这个,我们添加一个新的else if 语句块检查名字是否是‘Osama Bin Laden’,然后提供一个实体类级别的错误:
[HttpPost]public IActionResult Index(JobApplication jobApplication){if (string.IsOrEmpty(jobApplication.Name))ModelState.AddModelError(nameof(jobApplication.Name), "请输入用户名");else if (jobApplication.Name == "Osama Bin Laden")ModelState.AddModelError("", "你不能申请工作");// removed for clarity}
@model JobApplication@{ViewData["Title"] = "Job Application";}<style>.input-validation-error {border-color: red;}</style><h2>Job Application</h2>@*<div asp-validation-summary="All" class="text-danger"></div>*@<div asp-validation-summary="ModelOnly" class="text-danger"></div><form class="m-1 p-1" method="post"><div class="mb-3 row"><div class="col-sm-1"><label asp-for="Name" class="control-label"></label></div><div class="col-sm-11"><input asp-for="Name" class="form-control" /><span asp-validation-for="Name" class="text-danger"></span></div></div><div class="mb-3 row"><div class="col-sm-1"><label asp-for="DOB" class="control-label"></label></div><div class="col-sm-11"><input asp-for="DOB" type="text" asp-format="{0:d}" class="form-control" /><span asp-validation-for="DOB" class="text-danger"></span></div></div><div class="mb-3 row"><div class="col-sm-1"><label asp-for="Sex" class="control-label"></label></div><div class="col-sm-1"><input asp-for="Sex" type="radio" value="M" class="form-check" />男</div><div class="col-sm-1"><input asp-for="Sex" type="radio" value="F" class="form-check" />女</div><div class="col-sm-9"><span asp-validation-for="Sex" class="text-danger"></span></div></div><div class="mb-3 row"><div class="col-sm-1"><label asp-for="Experience" class="control-label"></label></div><div class="col-sm-11"><select asp-for="Experience" class="form-control"><option value="选择">选择</option><option value="0">新手</option><option value="1">0-1 年</option><option value="2">1-2 年</option><option value="3">2-3 年</option><option value="4">3-4 年</option><option value="5">4-5 年</option></select><span asp-validation-for="Experience" class="text-danger"></span></div></div><div class="mb-3 row"><div class="col-sm-1"></div><div class="col-sm-1"><input asp-for="TermsAccepted" class="form-label" /></div><div class="col-sm-10"><label asp-for="TermsAccepted" class="form-check-label">我接受条款 & 条件</label><span asp-validation-for="TermsAccepted" class="text-danger"></span></div></div><div class="mb-3 row"><div class="col-sm-11 offset-sm-1"><button type="submit" class="btn btn-primary">提交</button></div></div></form>
2 模型验证中使用Data Annotations
ASP.NET Core 内置了大量的验证特性,我们可以在实体类上应用这些规则来指定验证规则,这些特性位于该命名空间(System.ComponentModel.DataAnnotations),验证处理过程是即简单又快,也可以少些一些验证的代码
微软在该命名空间下提供了大量的验证特性,我们也可以在应用程序中使用他们来做验证,可以在模型类的属性指定特性来验证属性,特性中定义了一系列的验证规则
下面列出了常用的特性:
| 名称 | 描述 |
[Required(ErrorMessage = “Some Message”)] | 确保值不为空,默认值为的类型指定一个值 例如:int?, float?, string |
[StringLength(max,min)] | 给字符串长度指定一个范围(包含最小值和最大值).例如[StringLeght(2,5)] 允许字符串的长度是2到5 |
[Compare(“OtherProperty”)] | 确保应用这个特性的属性和指定的属性(即OtherProperty) 有相同的值 |
[Range(min,max)] | 确保数字的值位于最小值和最大值之间(包含最大和最小值) 例如:[Range(2,5)] 包含的值 2,3,4,5 |
[RegularExpression(“pattern”)] | 给指定的属性设置正则表单时,例如:邮件地址 |
现在我们进入JobApplication类并且引用命名空间System.ComponentModel.DataAnnotations,将特性添加到属性上:
using System.ComponentModel.DataAnnotations;namespace ModelBindingValidation.Models{public class JobApplication{[Required][Display(Name = "Job applicant name")]public string Name { get; set; }public DateTime DOB { get; set; }[Required(ErrorMessage = "Please select your sex")]public string Sex { get; set; }[Range(0, 5)]public string Experience { get; set; }[Range(typeof(bool), "true", "true", ErrorMessage = "You must accept the Terms")]public bool TermsAccepted { get; set; }}}
名字上我们应用了2个特性,分别是:Display Required
[Required][DisplayName("姓名")]public string Name { get; set; }
[Required(ErrorMessage = "你输入你的出生日期")]public DateTime? DOB { get; set; }
在上面的代码中,我们应用了[Required(ErrorMessage = "")] 特性,确保DOB字段的值不能为空,并且有正确的时间格式,以相同的方式我们把[Required]特性应用到Sex字段
[Range(0, 5)]public int Experience { get; set; }
[Range(typeof(bool), "true", "true", ErrorMessage = "你必须接受条款")][DisplayName("条款")]public bool TermsAccepted { get; set; }
我们不能在用户选择条款上应用[Required]特性,这是因为一个bool类型的字段,如果不选择的话,默认值是false,因此Required 对该属性不起任何作用
using AspNetCore.ModelValidation.Models;using Microsoft.AspNetCore.Mvc;namespace AspNetCore.ModelValidation.Controllers{public class JobController : Controller{public IActionResult Index(){return View();}[HttpPost]public IActionResult Index(JobApplication jobApplication){if (ModelState.IsValid)return View("Accepted", jobApplication);elsereturn View();}}}
现在我们仅仅验证ModelState对象的IsValid属性,重新运行应用程序并且看到表单和之前一样工作使用简单的代码
下面代码包含action方法的验证:
[HttpPost]public IActionResult Index(JobApplication jobApplication){if (jobApplication.Name == "Osama Bin Laden")ModelState.AddModelError(nameof(jobApplication.Name), "You cannot apply for the Job");if (jobApplication.DOB > DateTime.Now)ModelState.AddModelError(nameof(jobApplication.DOB), "Date of Birth cannot be in the future");else if (jobApplication.DOB < new DateTime(1980, 1, 1))ModelState.AddModelError(nameof(jobApplication.DOB), "Date of Birth should not be before 1980");if (ModelState.IsValid)return View("Accepted", jobApplication);elsereturn View();}
2.1 模型验证Email地址
^[a-zA-Z0-9_\\.-]+@([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$using System.ComponentModel.DataAnnotations;namespace ModelBindingValidation.Models{public class JobApplication{[Required][Display(Name = "Job applicant name")]public string Name { get; set; }public DateTime DOB { get; set; }[Required(ErrorMessage = "Please select your sex")]public string Sex { get; set; }[Range(0, 5)]public string Experience { get; set; }[Range(typeof(bool), "true", "true", ErrorMessage = "You must accept the Terms")]public bool TermsAccepted { get; set; }[RegularExpression("^[a-zA-Z0-9_\\.-]+@([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$", ErrorMessage = "E-mail is not valid")]public string Email { get; set; }}}
进入View 添加如下代码
@model JobApplication@{ViewData["Title"] = "Job Application";}<style>.input-validation-error {border-color: red;}</style><h2>Job Application</h2>@*<div asp-validation-summary="All" class="text-danger"></div>*@<div asp-validation-summary="ModelOnly" class="text-danger"></div><form class="m-1 p-1" method="post"><div class="mb-3 row"><div class="col-sm-1"><label asp-for="Name" class="control-label"></label></div><div class="col-sm-11"><input asp-for="Name" class="form-control" /><span asp-validation-for="Name" class="text-danger"></span></div></div><div class="mb-3 row"><div class="col-sm-1"><label asp-for="DOB" class="control-label"></label></div><div class="col-sm-11"><input asp-for="DOB" type="text" asp-format="{0:d}" class="form-control" /><span asp-validation-for="DOB" class="text-danger"></span></div></div><div class="mb-3 row"><div class="col-sm-1"><label asp-for="Email" class="control-label"></label></div><div class="col-sm-11"><input asp-for="Email" type="text" asp-format="{0:d}" class="form-control" /><span asp-validation-for="Email" class="text-danger"></span></div></div><div class="mb-3 row"><div class="col-sm-1"><label asp-for="Sex" class="control-label"></label></div><div class="col-sm-1"><input asp-for="Sex" type="radio" value="M" class="form-check" />男</div><div class="col-sm-1"><input asp-for="Sex" type="radio" value="F" class="form-check" />女</div><div class="col-sm-9"><span asp-validation-for="Sex" class="text-danger"></span></div></div><div class="mb-3 row"><div class="col-sm-1"><label asp-for="Experience" class="control-label"></label></div><div class="col-sm-11"><select asp-for="Experience" class="form-control"><option value="选择">选择</option><option value="0">新手</option><option value="1">0-1 年</option><option value="2">1-2 年</option><option value="3">2-3 年</option><option value="4">3-4 年</option><option value="5">4-5 年</option></select><span asp-validation-for="Experience" class="text-danger"></span></div></div><div class="mb-3 row"><div class="col-sm-1"></div><div class="col-sm-1"><input asp-for="TermsAccepted" class="form-label" /></div><div class="col-sm-10"><label asp-for="TermsAccepted" class="form-check-label">我接受条款 & 条件</label><span asp-validation-for="TermsAccepted" class="text-danger"></span></div></div><div class="mb-3 row"><div class="col-sm-11 offset-sm-1"><button type="submit" class="btn btn-primary">提交</button></div></div></form>
当Email格式不正确时,将显示下面错误消息:
注意:我们也能使用[EmailAddress] 验证特性做email验证
[EmailAddress]public string Email { get; set; }
3 自定义模型验证
public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context){...}
姓名 | 描述 |
Model | 返回验证的属性的值 |
Container | 返回属性所拥有的对象 |
ActionContext | 提供上下文数据 |
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;namespace AspNetCore.ModelValidation.Infrastructure{public class CustomDate : Attribute, IModelValidator{public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context){if (Convert.ToDateTime(context.Model) > DateTime.Now)return new List<ModelValidationResult> {new ModelValidationResult("", "日期不能大于当前日期")};else if (Convert.ToDateTime(context.Model) < new DateTime(1980, 1, 1))return new List<ModelValidationResult> {new ModelValidationResult("", "日期必须在1980年以前")};elsereturn Enumerable.Empty<ModelValidationResult>();}}}
现在在DOB字段上添加这个特性:
using AspNetCore.ModelValidation.Infrastructure;using System.ComponentModel;using System.ComponentModel.DataAnnotations;namespace AspNetCore.ModelValidation.Models{public class JobApplication{[Required(ErrorMessage ="姓名不能为空")][DisplayName("姓名")]public string Name { get; set; }[DisplayName("出生日期")][Required(ErrorMessage = "请输入你的出生日期")][CustomDate]public DateTime? DOB { get; set; }[Required(ErrorMessage = "请选择性别")][DisplayName("性别")]public string Sex { get; set; }[Range(0, 5,ErrorMessage ="工作年限必须在0-5年")][DisplayName("工作经验")]public string? Experience { get; set; }[Range(typeof(bool), "true", "true", ErrorMessage = "你必须接受条款")][DisplayName("条款")]public bool TermsAccepted { get; set; }[RegularExpression("^[a-zA-Z0-9_\\.-]+@([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$", ErrorMessage = "电子邮件不正确")][DisplayName("电子邮件")]public string Email { get; set; }}}
[HttpPost]public IActionResult Index(JobApplication jobApplication){if (ModelState.IsValid)return View("Accepted", jobApplication);elsereturn View();}
现在,我们测试一下,下面图片显示错误消息:
namespace AspNetCore.ModelValidation.Infrastructure{public class NameValidate : Attribute, IModelValidator{public string[] NotAllowed { get; set; }public string ErrorMessage { get; set; }public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context){if (NotAllowed.Contains(context.Model as string))return new List<ModelValidationResult> {new ModelValidationResult("", ErrorMessage)};elsereturn Enumerable.Empty<ModelValidationResult>();}}}
[Required][Display(Name = "Job applicant name")][NameValidate(NotAllowed = new string[] { "Osama Bin Laden", "Saddam Hussain", "Mohammed Gaddafi" }, ErrorMessage = "You cannot apply for the Job")]public string Name { get; set; }
4 客户端验证
@model JobApplication@{Layout = "_Layout";ViewData["Title"] = "Job Application";}@section scripts {<script src="~/lib/jquery/dist/jquery.min.js"></script><script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script><script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>}<style>.input-validation-error {border-color: red;}</style><h2>Job Application</h2>
客户端验证不能工作针对Range特性处理bool值,因此你需要注释掉Range特性,因此需要在客户端单独处理
//[Range(typeof(bool), "true", "true", ErrorMessage = "You must accept the Terms")]public bool TermsAccepted { get; set; }
客户端验证也不支持像用户自定义模型证 [CustomDate]和[NameValidate]这对这些验证你需要在客户端创建验证
5 ASP.NET Core 远程验证
远程验证是通过异步方式验证,尽管看上去像客户端验证,但实际上通过Ajax在服务器端完成,远程验证在服务器端进行,当控件失去焦点时出发验证验证,而不是点击提交按钮
为了创建远程验证,我们需要添加一个action方法,返回JsonResult对象,有一个DOB的参数
我们把DOB属性上验证Attribute移除掉,添加一个新的action方法调用ValidateDate在JobController,代码如下:
public JsonResult ValidateDate(DateTime DOB){if (DOB > DateTime.Now)return Json("日期必须大于当前时间");else if (DOB < new DateTime(1980, 1, 1))return Json("日期不能再1980年以前");elsereturn Json(true);}
using AspNetCore.ModelValidation.Infrastructure;using Microsoft.AspNetCore.Mvc;using System.ComponentModel;using System.ComponentModel.DataAnnotations;namespace AspNetCore.ModelValidation.Models{public class JobApplication{[][][] { "Osama Bin Laden", "Saddam Hussain", "Mohammed Gaddafi" },ErrorMessage = "你不能申请这份工作")]public string Name { get; set; }[][][]public DateTime? DOB { get; set; }[][]public string Sex { get; set; }[][]public string? Experience { get; set; }[][]public bool TermsAccepted { get; set; }[][][]public string Email { get; set; }}}
现在我们输入DOB字段来检查验证,注意当鼠标移走时,远程验证将被调用
源代码地址
参考文献
https://www.yogihosting.com/aspnet-core-model-validation/#custom-model-validation

本文暂时没有评论,来添加一个吧(●'◡'●)