Asp.net-Mvc

使用 DataAnnotationsModelValidatorProvider.RegisterAdapter 的 MVC 2 與 MVC 3 自定義驗證屬性

  • June 15, 2013

我讀過一些文章,但現在找不到它,因為在 MVC 3 中實際上不需要創建驗證器,只需要創建屬性。這是真的?我確實說我發現屬性上有 IClientValidatable 令人困惑。那麼,如果註解具有客戶端腳本名稱(IClientValidatable)和驗證能力(ValidationAttribute IsValid),DataAnnotationsModelValidator 類會做什麼?

如果我不必在全域中使用 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;
   }
}

最後一段程式碼替換所有其他程式碼有問題嗎?為什麼我要保留驗證器類?

瘋狂飛鏢,

IClientValidatable介面是在MVC3中添加的。

您的第二個範例顯示了對這個新介面的有效使用。您是正確的,它不必註冊,它將提供必要的客戶端驗證規則,以及進行必要的伺服器端驗證。

來吧,享受它。

輔導員本

當我使用 CrazyDart 的最後一個選項時,伺服器端部分在 MVC4 中執行良好。

除非我無法讓客戶端驗證正常工作。它從不檢查客戶端的必填欄位(儘管添加了一些標籤)。

我還查看了 Simon Ince 的第二篇博文(第一篇是海報的靈感):http: //blogs.msdn.com/b/simonince/archive/2011/02/04/conditional-validation-in -asp-net-mvc-3.aspx

引用自:https://stackoverflow.com/questions/6495510