4

是否可以實現客戶端驗證自定義ValidationAttribute,它在Class作用域中使用?例如我的MaxLengthGlobal,它應該確保所有輸入字段的全局最大限制。使用AttributeTargets.Class自定義驗證屬性的客戶端驗證

[AttributeUsage(AttributeTargets.Class)] 
public class MaxLengthGlobalAttribute : ValidationAttribute, IClientValidatable 
{ 
    public int MaximumLength 
    { 
     get; 
     private set; 
    } 

    public MaxLengthGlobalAttribute(int maximumLength) 
    { 
     this.MaximumLength = maximumLength; 
    } 

    public override bool IsValid(object value) 
    { 
     var properties = TypeDescriptor.GetProperties(value); 

     foreach (PropertyDescriptor property in properties) 
     { 
      var stringValue = property.GetValue(value) as string; 

      if (stringValue != null && (stringValue.Length > this.MaximumLength)) 
      { 
       return false; 
      } 
     } 

     return true; 
    } 

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    {  
     var rule = new ModelClientValidationRule 
     { 
      ErrorMessage = this.FormatErrorMessage(metadata.GetDisplayName()), 
      ValidationType = "maxlengthglobal", 
     }; 

     rule.ValidationParameters.Add("maxlength", this.MaximumLength);   
     yield return rule; 
    } 
} 

謝謝。

回答

1

不,不可能。抱歉。

4

我在找同樣問題的解決方案時找到了這個答案,並提出了一個解決方法。

代替1 ValidationAttribute,具有2:

1)一種ServerValidationAttribute將在類,並且將不執行IClientValidatable。

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 
public class MyCustomServerValidationAttribute : ValidationAttribute 
{ 
    public override bool IsValid(object value) 
    { 
     // remember to cast to the class type, not property type 
     // ... return true or false 
    } 
} 

2)一個ClientValidationAttribute將在字段/屬性,並會實施IClientValidatable,但覆蓋的IsValid總是返回true。

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, 
    AllowMultiple = false, Inherited = true)] 
public class MyCustomClientValidationAttribute : ValidationAttribute, 
    IClientValidatable 
{ 
    public override bool IsValid(object value) 
    { 
     return true; 
    } 

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(
     ModelMetadata metadata, ControllerContext context) 
    { 
     var rule = new ModelClientValidationRule 
     { 
      ErrorMessage = ErrorMessage, 
      ValidationType = "mycustomvalidator", 
     }; 

     var viewContext = (ViewContext)context; 
     var dependentProperty1 = viewContext.ViewData.TemplateInfo 
      .GetFullHtmlFieldId("DependentProperty1"); 
     //var prefix = viewContext.ViewData.TemplateInfo.HtmlFieldPrefix; 

     rule.ValidationParameters.Add("dependentproperty1", dependentProperty1); 

     yield return rule; 
    } 
} 

在客戶端上執行時,服務器屬性被忽略,反之亦然。

如果您需要在該類上具有驗證屬性,則可能會針對多個字段進行驗證。我放棄了一些樣板代碼以將其他參數傳遞給客戶端驗證方法,但未按預期工作。在我的實際代碼中,我已經註釋掉了viewContext和dependentProperty1變量,並將一個「DependentProperty1」字符串傳遞給了rule.ValidationParameters.Add方法的第二個參數。出於某種原因,我收到了不正確的HtmlFieldPrefix。如果任何人都可以在這方面幫助請評論...

無論如何,你最終像這樣的視圖模型:

[MyCustomServerValidation(ErrorMessage = MyCustomValidationMessage)] 
public class MyCustomViewModel 
{ 
    private const string MyCustomValidationMessage = "user error!"; 

    [Display(Name = "Email Address")] 
    [MyCustomClientValidation(ErrorMessage = MyCustomValidationMessage)] 
    public string Value { get; set; } 

    [HiddenInput(DisplayValue = false)] 
    public string DependentProperty1 { get; set; } 
} 

客戶端腳本是這樣的:

/// <reference path="jquery-1.6.2.js" /> 
/// <reference path="jquery.validate.js" /> 
/// <reference path="jquery.validate.unobtrusive.js" /> 

$.validator.addMethod('mycustomvalidator', function (value, element, parameters) { 
    var dependentProperty1 = $('#' + parameters['dependentproperty1']).val(); 
    // return true or false 
}); 
$.validator.unobtrusive.adapters.add('mycustomvalidator', ['dependentproperty1'], 
    function (options) { 
     options.rules['mycustomvalidator'] = { 
      dependentproperty1: options.params['dependentproperty1'] 
     }; 
     options.messages['mycustomvalidator'] = options.message; 
    } 
); 

像一個視圖這:

@Html.EditorFor(m => m.Value) 
@Html.EditorFor(m => m.DependentProperty1) 
@Html.ValidationMessageFor(m => m.Value) 
@Html.ValidationMessageFor(m => m) 

然後,如果你有客戶端驗證被禁用,@Html.ValidationMessageFor(m => m)顯示在代替財產的一個。

+0

這工作就像一個魅力!謝謝! – jhdrn 2012-10-19 05:57:51