Data Annotations and Validdation -By Scott Allen
本章内容
- 为验证添加数据注解
- 创建自定义验证逻辑
- 使用元数据模型注解
-使用验证注解
Required
[Required] public string FirstName { get; set; } [Required] public string LastName { get; set; }

StringLength
[Required] [StringLength(160)] public string FirstName { get; set; } [Required] [StringLength(160)] public string LastName { get; set; }

RegularExpression
[RegularExpression(@”[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}”)] public string Email { get; set; }

Range
[Range(35,44)] public int Age { get; set; } [Range(typeof(decimal), “0.00”, “49.99”)] public decimal Price { get; set; }
-Validation Attributes from System.Web.Mvc
Remote
[Remote(“CheckUserName”, “Account”)] public string UserName { get; set; } public JsonResult CheckUserName(string username) { var result = Membership.FindUsersByName(username).Count == 0; return Json(result, JsonRequestBehavior.AllowGet); }
Compare
[RegularExpression(@”[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}”)] public string Email { get; set; } [Compare(“Email”)] public string EmailConfirm { get; set; }

自定义错误信息及本地化
[RegularExpression(@”[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}”, ErrorMessage=”Email doesn’t look like a valid email address.”)] public string Email { get; set; } [Required(ErrorMessage=”Your last name is required”)] [StringLength(160, ErrorMessage=”Your last name is too long”)] public string LastName { get; set; }
[Required(ErrorMessage=”Your {0} is required.”)]
[StringLength(160, ErrorMessage=”{0} is too long.”)]
public string LastName { get; set; }

读取资源文件(下面代码假设资源文件名为ErrorMessages.resx,它包含LastNamerequired及LastNameTooLong):
[Required(ErrorMessageResourceType=typeof(ErrorMessages), ErrorMessageResourceName=”LastNameRequired”)] [StringLength(160, ErrorMessageResourceType = typeof(ErrorMessages), ErrorMessageResourceName = “LastNameTooLong”)] public string LastName { get; set; }
-了解注解是如何工作的
首先,mvc框架是在模型绑定期间执行验证逻辑。如第四章介绍的,下面两种情况都会触发模型绑定:
[HttpPost] public ActionResult Create(Album album) { // the album parameter was created via model binding // .. } [HttpPost] public ActionResult Edit(int id, FormCollection collection) { var album = storeDB.Albums.Find(id); if(TryUpdateModel(album)) { // ... } }
当模型绑定完成属性更新后,模型绑定通过当前模型的元数据来获取所有验证。运行时提供了DataAnnotationsModelValidator来处理数据注解,它能够找到所有验证属性并执行验证逻辑。模型绑定会捕获所有验证失败的规则并存放在模型状态中。
模型绑定时会对模型状态产生影响,这不仅是因为模型状态包含了所有属性值,模型状态还包含了所有属性的关联错误(每个错误又与模型对像本身相关联)。如果模型状态里面包含错误,那么ModelState.isValid的值将返回false。
假设用户在付款时没有填写LastName就将信息提交了,由于Required验证注解的作用,下面的表达式在模型绑定后都会返回ture:
ModelState.IsValid == false ModelState.IsValidField(“LastName”) == false ModelState[”LastName”].Errors.Count > 0
查看错误信息:
var lastNameErrorMessage = ModelState[“LastName”].Errors[0].ErrorMessage;
当然,你极少情况下需要这样去查看错误信息。直接在视图中使用Validationmessage helper显示错误信息即可:
@Html.ValidationMessageFor(m => m.LastName)
控制器行为通常只需要判断ModelState是否为已验证就行了。
[HttpPost] public ActionResult AddressAndPayment(Order newOrder) { if (ModelState.IsValid) { newOrder.Username = User.Identity.Name; newOrder.OrderDate = DateTime.Now; storeDB.Orders.Add(newOrder); storeDB.SaveChanges(); // Process the order var cart = ShoppingCart.GetCart(this); cart.CreateOrder(newOrder); return RedirectToAction(“Complete”, new { id = newOrder.OrderId }); } // Invalid -- redisplay with errors return View(newOrder); }
[HttpPost] public ActionResult AddressAndPayment(FormCollection collection) { var newOrder = new Order(); TryUpdateModel(newOrder); if (ModelState.IsValid) { newOrder.Username = User.Identity.Name; newOrder.OrderDate = DateTime.Now; storeDB.Orders.Add(newOrder); storeDB.SaveChanges(); // Process the order var cart = ShoppingCart.GetCart(this); cart.CreateOrder(newOrder); return RedirectToAction(“Complete”, new { id = newOrder.OrderId }); } // Invalid -- redisplay with errors return View(newOrder); }
-自定义验证逻辑
自定义注解
using System.ComponentModel.DataAnnotations; public class MaxWordsAttribute : ValidationAttribute { public MaxWordsAttribute(int maxWords):base(“{0} has too many words.”) { _maxWords = maxWords; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
if (value != null) { var valueAsString = value.ToString(); if (valueAsString.Split('').Length > _maxWords) { var errorMessage = FormatErrorMessage( validationContext.DisplayName); return new ValidationResult(errorMessage); } } return ValidationResult.Success; } private readonly int _maxWords; }
[Required] [StringLength(160)] [MaxWords(10)] public string LastName { get; set; } [Required] [StringLength(160)] [MaxWords(10, ErrorMessage=”There are too many words in {0}”)] public string LastName { get; set; }
IValidatableObject
public class Order : IValidatableObject { public IEnumerable<ValidationResult> Validate( ValidationContext validationContext) { if (LastName != null && LastName.Split(‘ ‘).Length > 10) { yield return new ValidationResult(“The last name has too many words!”, new []{“LastName”}); } } // rest of Order implementation and properties // ... }
当需要通过多个属性来判断验证结果时,可以使用这种方法来自定义验证。
-用于显示与编辑的注解
Display
[Required] [StringLength(160, MinimumLength=3)] [Display(Name=”First Name”)] public string FirstName { get; set; }
[Display(Name = “Last Name”, Order = 15001)] [MaxWords(10, ErrorMessage = “There are too many words in {0}”)] public string LastName { get; set; } [Required] [StringLength(160, MinimumLength=3)] [Display(Name=”First Name”, Order=15000)] public string FirstName { get; set; }
Order的作用是排序,默认值是10000,各项会以该值按升序排列。
ScaffoldColumn
[ScaffoldColumn(false)] public string Username { get; set; }
作用是在EditorForModel及DisplayForModel中隐藏相关字段。
DisplayFormat
[DisplayFormat(ApplyFormatInEditMode=true, DataFormatString=”{0:c}”)] public decimal Total { get; set; } result: $12.10
ReadOnly
[ReadOnly(true)] public decimal Total { get; set; }
设置了ReadOnly的属性在模型绑定时不会被更新值。
DataType
[Required] [DataType(DataType.Password)] [Display(Name = “Password”)] public string Password { get; set; }
除了Password,还有其他类型设置: Currency, Date, Time, and MultilineText
HiddenInput
生成一个type类型为hidden的input元素
-SUMMARY
本章你了解了如何给验证添加数据注解,运行时如何使用模型元数据及模型绑定。验证同时提供了客户端及服务端的验证而无需编写额外的代码。另外你还学习了如何创建自定义验证,如何通过数据注解来改变html helper所生成的html代码。
END
浙公网安备 33010602011771号