上一篇文章也有介绍使用验证特性类指定Mode验证规则,但是介绍的不是很详细,下面详细深入谈谈如何使用.NET内置验证特性类指定Mode验证规则及自定义符合自己的业务规则的验证特性类的方法。
一、使用内置的.NET验证特性类
在程序集 System.ComponentModel.DataAnnotations.dll, v4.0.0.0中为我们定义很多有用的验证特性类。最常用类如下:
- CompareAttribute 提供比较两个属性的属性。
- CreditCardAttribute 指定数据字段值是信用卡号码。
- CustomValidationAttribute 指定自定义的验证方法来验证属性或类的实例。
- DataTypeAttribute 指定要与数据字段关联的附加类型的名称。
- DisplayAttribute 提供一个通用特性,使您可以为实体分部类的类型和成员指定可本地化的字符串。
- EmailAddressAttribute 确认一电子邮件地址。
- MaxLengthAttribute 指定属性中允许的数组或字符串数据的最大长度。
- MinLengthAttribute 指定属性中允许的数组或字符串数据的最小长度。
- PhoneAttribute 使用电话号码的正则表达式,指定数据字段值是一个格式正确的电话号码。
- RangeAttribute 指定数据字段值的数值范围约束。
- RegularExpressionAttribute 指定 ASP.NET 动态数据中的数据字段值必须与指定的正则表达式匹配。
- RequiredAttribute 指定需要数据字段值。
- UrlAttribute 提供 URL 验证。
下面我们看看怎么使用这些内置的验证特性类来定义我们Model类,并让它字段必须满足一定的规则:
- using System;
- using System.Collections.Generic;
- using System.ComponentModel.DataAnnotations;
- using System.linq;
- using System.Web;
- namespace mvcModelBindingDemo.Models
- {
- public class Appointment
- {
- [Required(ErrorMessage="ClientName为必填项目")]
- public string ClientName { get; set; }
- [DataType(DataType.Date)]
- public DateTime Date { get; set; }
- public bool TermsAccepted { get; set; }
- }
- }
二、扩展内置的.NET验证特性类
2、1、自定义一个属性验证特性类
下面我们定义FutureDateAttribute来验证一个字段必须为日期且其值必须大于当前时间。
- using System;
- using System.ComponentModel.DataAnnotations;
- namespace MVCModelBindingDemo.Infrastructure {
- public class FutureDateAttribute : RequiredAttribute {
- public override bool IsValid(object value) {
- return base.IsValid(value) && ((DateTime)value) > DateTime.Now;
- }
- }
- }
定义好了这个特性类,使用和内置的验证特性类没有区别。如下:
- using System;
- using System.Collections.Generic;
- using System.ComponentModel.DataAnnotations;
- using System.Linq;
- using System.Web;
- namespace MVCModelBindingDemo.Models
- {
- public class Appointment
- {
- [Required(ErrorMessage="ClientName为必填项目")]
- public string ClientName { get; set; }
- [DataType(DataType.Date)]
- [FutureDate(ErrorMessage="请输入一个未来的日期")]
- public DateTime Date { get; set; }
- public bool TermsAccepted { get; set; }
- }
- }
除了定义一个针对某个字段进行验证的的特性类,我们还可以自定义一个Model验证特性类,在里面依次进行验证每个字段。下面定义一个Model验证特性类NoJoeOnMondaysAttribute用来验证,当ClientName为Joe时,Date不能为星期天。
- using System;
- using System.ComponentModel.DataAnnotations;
- using MVCModelBindingDemo.Models;
- namespace ModelValidation.Infrastructure {
- public class NoJoeOnMondaysAttribute : ValidationAttribute {
- public NoJoeOnMondaysAttribute() {
- ErrorMessage = "Joe cannot book appointments on Mondays";
- }
- public override bool IsValid(object value) {
- Appointment app = value as Appointment;
- if (app == null || string.IsNullOrEmpty(app.ClientName) ||
- app.Date == null) {
- //当没model为空或者没有ClientName为空或Date为null直接返回true
- return true;
- } else {
- return !(app.ClientName == "Joe" &&
- app.Date.DayOfWeek == DayOfWeek.Monday);
- }
- }
- }
- }
在Model中定义使用这个Model验证特性类:
- using System;
- using System.ComponentModel.DataAnnotations;
- using MVCModelBindingDemo.Infrastructure;
- namespace MVCModelBindingDemo.Models
- {
- [NoJoeOnMondays]
- public class Appointment
- {
- [Required(ErrorMessage="ClientName为必填项目")]
- public string ClientName { get; set; }
- [DataType(DataType.Date)]
- [FutureDate(ErrorMessage="请输入一个未来的日期")]
- public DateTime Date { get; set; }
- public bool TermsAccepted { get; set; }
- }
- }
三、MVC 中定义自验证Model
什么是自验证Model呢?简单的说就是Model验证的逻辑放在Model类中,如下面的代码:
- using System;
- using System.Collections.Generic;
- using System.ComponentModel.DataAnnotations;
- using MVCModelBindingDemo.Infrastructure;
- namespace MVCModelBindingDemo.Models {
- public class Appointment : IValidatableObject {
- public string ClientName { get; set; }
- [DataType(DataType.Date)]
- public DateTime Date { get; set; }
- public bool TermsAccepted { get; set; }
- public IEnumerable<ValidationResult> Validate(ValidationContext
- validationContext) {
- List<ValidationResult> errors = new List<ValidationResult>();
- if (string.IsNullOrEmpty(ClientName)) {
- errors.Add(new ValidationResult("Please enter your name"));
- }
- if (DateTime.Now > Date) {
- errors.Add(new ValidationResult("Please enter a date in the future"));
- }
- if (errors.Count == 0 && ClientName == "Joe"
- && Date.DayOfWeek == DayOfWeek.Monday) {
- errors.Add(
- new ValidationResult("Joe cannot book appointments on Mondays"));
- }
- if (!TermsAccepted) {
- errors.Add(new ValidationResult("You must accept the terms"));
- }
- return errors;
- }
- }
- }
当MVC框架的model binder为我们model的每个属性赋好值之后,这个Validate方法将会被调用。可能有的人不喜欢把验证逻辑放在Model中,因为他们这样违反了Model的单一职责性,但是我觉得在MVC架构中这样把验证逻辑放在model中其实也不失一种不错的选择,这样充分的发挥了MVC中三大重要元素这一的Model重要作用。