ASP.NET MVC的四种验证编程方式

2019-05-23 00:58:54丽君

public interface IValidatableObject 
{ 
  IEnumerable<ValidationResult> Validate( ValidationContext validationContext); 
} 

如上面的代码片断所示,IValidatableObject接口具有唯一的方法Validate,针对自身的验证就实现在该方法中。对于上面演示实例中定义的数据类型Person,我们可以按照如下的形式将它定义成自我验证类型。

public class Person: IValidatableObject 
{ 
  [DisplayName("姓名")] 
  public string Name { get; set; } 
 
  [DisplayName("性别")] 
  public string Gender { get; set; } 
 
  [DisplayName("年龄")] 
  public int? Age { get; set; } 
 
  public IEnumerable<ValidationResult> Validate( ValidationContext validationContext) 
  { 
    Person person = validationContext.ObjectInstance as Person; 
    if (null == person) 
    { 
      yield break; 
    } 
    if(string.IsNullOrEmpty(person.Name)) 
    { 
      yield return new ValidationResult("'Name'是必需字段", new string[]{"Name"}); 
    } 
 
    if (string.IsNullOrEmpty(person.Gender)) 
    { 
      yield return new ValidationResult("'Gender'是必需字段", new string[] { "Gender" }); 
    } 
    else if (!new string[]{"M","F"}.Any( g=>string.Compare(person.Gender,g, true) == 0)) 
    { 
      yield return new ValidationResult("有效'Gender'必须是'M','F'之一",  new string[] { "Gender" }); 
    } 
 
    if (null == person.Age) 
    { 
      yield return new ValidationResult("'Age'是必需字段",  new string[] { "Age" }); 
    } 
    else if (person.Age > 25 || person.Age < 18) 
    { 
      yield return new ValidationResult("'Age'必须在18到25周岁之间",  new string[] { "Age" }); 
    }       
  } 
} 

如上面的代码片断所示,我们让Person类型实现了IValidatableObject接口。在实现的Validate方法中,我们从验证上下文中获取被验证的Person对象,并对其属性成员进行逐个验证。如果数据成员没有通过验证,我们通过一个ValidationResult对象封装错误消息和数据成员名称(属性名),该方法最终返回的是一个元素类型为ValidationResult的集合。在不对其他代码作任何改动的情况下,我们直接运行该程序并在输入不合法数据的情况下提交表单后依然会得到如图1所示的输出结果。

四、让数据类型实现IDataErrorInfo接口

上面我们让数据类型实现IValidatableObject接口并将具体的验证逻辑定义在实现的Validate方法中,这样的类型能够被ASP.NET MVC所识别,后者会自动调用该方法对绑定的数据对象实施验证。如果我们让数据类型实现IDataErrorInfo接口也能实现类似的自动化验证效果。

IDataErrorInfo接口定义在“System.ComponentModel”命名空间下,它提供了一种标准的错误信息定制方式。如下面的代码片段所示,IDataErrorInfo具有两个成员,只读属性Error用于获取基于自身的错误消息,而只读索引用于返回指定数据成员的错误消息。