2011-06-27 76 views
14

我读过一些文章,但现在无法找到它,在MVC 3中并没有真正需要创建一个Validator,只有属性。这是真的?我确实说我发现这个属性上有IClientValidatable,令人困惑。那么,如果注释具有客户端脚本名称(IClientValidatable),并且验证(ValidationAttribute IsValid)的能力,DataAnnotationsModelValidator类会做什么?MVC 2与MVC 3自定义验证属性使用DataAnnotationsModelValidatorProvider.RegisterAdapter

如果我不必在全球范围内使用Validator注册Attribute,那将会非常好。这可以做到吗?我读了一些不好的建议吗?

编辑:有趣的是,我只是通过排除验证器来测试它,把所有的逻辑放在IsValid中,它工作的很好。我想唯一可能会丢失的是控制器上下文,但我不确定这在验证中是有用的。如果我需要服务,则IsValid具有ValidationContext,其中包含ServiceContainer。任何真正的缺点,我不在这里接受?

编辑2: 我将开始与从这个例子的验证:http://blogs.msdn.com/b/simonince/archive/2010/06/04/conditional-validation-in-mvc.aspx

的属性:

public class RequiredIfAttribute : ValidationAttribute, IClientValidatable 
{ 
    private RequiredAttribute innerAttribute = new RequiredAttribute(); 
    public string DependentProperty { get; set; } 
    public object TargetValue { get; set; } 

    public RequiredIfAttribute(string dependentProperty, object targetValue) 
    { 
     this.DependentProperty = dependentProperty; 
     this.TargetValue = targetValue; 
    } 

    public override bool IsValid(object value) 
    { 
     return innerAttribute.IsValid(value); 
    } 

    public System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    { 
     ModelClientValidationRule modelClientValidationRule = new ModelClientValidationRule() 
     { 
      ErrorMessage = FormatErrorMessage(metadata.DisplayName), 
      ValidationType = "requiredifattribute" 
     }; 
     modelClientValidationRule.ValidationParameters.Add("requiredifattribute", DependentProperty); 
     yield return modelClientValidationRule; 
    } 
} 

确认者:

public class RequiredIfValidator : DataAnnotationsModelValidator<RequiredIfAttribute> 
{ 
    public RequiredIfValidator(ModelMetadata metadata, ControllerContext context, RequiredIfAttribute attribute) 
     : base(metadata, context, attribute) 
    { 
    } 

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() 
    { 
     return base.GetClientValidationRules(); 
    } 

    public override IEnumerable<ModelValidationResult> Validate(object container) 
    { 
     var field = Metadata.ContainerType.GetProperty(Attribute.DependentProperty); 
     if (field != null) 
     { 
      var value = field.GetValue(container, null); 
      if ((value == null && Attribute.TargetValue == null) || 
       (value.Equals(Attribute.TargetValue))) 
      { 
       if (!Attribute.IsValid(Metadata.Model)) 
        yield return new ModelValidationResult { Message = ErrorMessage }; 
      } 
     } 
    } 
} 

利用上述当前代码,我需要在Global.asax.cs文件中注册:

DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredIfAttribute), typeof(RequiredIfValidator)); 

但是,如果我移动到一切只是属性,我没有进行注册:

public class RequiredIfAttribute : ValidationAttribute, IClientValidatable 
{ 
    private RequiredAttribute innerAttribute = new RequiredAttribute(); 
    public string DependentProperty { get; set; } 
    public object TargetValue { get; set; } 

    public RequiredIfAttribute(string dependentProperty, object targetValue) 
    { 
     this.DependentProperty = dependentProperty; 
     this.TargetValue = targetValue; 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     var field = validationContext.ObjectInstance.GetType().GetProperty(DependentProperty); 
     if (field != null) 
     { 
      var dependentValue = field.GetValue(validationContext.ObjectInstance, null); 
      if ((dependentValue == null && TargetValue == null) || 
       (dependentValue.Equals(TargetValue))) 
      { 
       if (!innerAttribute.IsValid(value)) 
        return new ValidationResult(ErrorMessage); 
      } 
     } 
     return ValidationResult.Success; 
    } 

    public System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    { 
     ModelClientValidationRule modelClientValidationRule = new ModelClientValidationRule() 
     { 
      ErrorMessage = FormatErrorMessage(metadata.DisplayName), 
      ValidationType = "requiredifattribute" 
     }; 
     modelClientValidationRule.ValidationParameters.Add("requiredifattribute", DependentProperty); 
     yield return modelClientValidationRule; 
    } 
} 

有没有用代码替代所有其他代码的最后一位的问题呢?我为什么要保留验证器类?

+0

你在哪里阅读这个建议? –

+0

我希望我能找到它,但我不能。这更多是对某个人的帖子的评论。你怎么看待这件事? – CrazyDart

+0

目前我不认为什么,因为我仍然试图了解问题是什么。我只是希望看到更多的上下文,特定的代码示例等等,这就是为什么我要求源代码以尝试查看更多上下文,因为您在问题中没有提供足够的内容。希望你会提供一些特定的代码示例来说明你遇到的问题。 –

回答

10

CrazyDart,

在MVC3加入IClientValidatable接口。

你的第二个例子显示了这个新接口的有效使用。你是正确的,它不必注册,它将提供必要的客户端验证规则,以及进行必要的服务器端验证。

继续前进,享受它。

counsellorben

+1

事实证明,你是正确的。我将使用IClientValidatable,在做这件事时我会看起来很棒。 ;-) – CrazyDart

+1

我认为IClientValidatable仍然需要为我的IClientValidatable理解添加jQuery验证适配器和验证方法的客户端脚本。 – afr0