使用AttributeTargets.Class对自定义ValidationAttribute进行客户端validation

是否可以为Class范围中使用的自定义ValidationAttribute实现客户端站点validation? 例如我的MaxLengthGlobal,它应该确保所有输入字段的全局最大限制。

[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 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 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 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; } } 

在客户端上执行时,将忽略server属性,反之亦然。

如果您需要在类上具有validation属性,则可能会针对多个字段进行validation。 我删除了一些样板代码,用于将其他参数传递给客户端validation方法,但它没有按预期工作。 在我的实际代码中,我已经注释掉了viewContext和dependentProperty1变量,并且只是将“DependentProperty1”字符串传递给rule.ValidationParameters.Add方法的第二个参数。 出于某种原因,我得到了一个不正确的HtmlFieldPrefix。 如果有人可以帮忙,请评论……

无论如何,你最终得到一个像这样的viewmodel:

 [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; } } 

像这样的客户端脚本:

 ///  ///  ///  $.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) 

然后,如果禁用了客户端validation,则会显示@Html.ValidationMessageFor(m => m)而不是属性。

Interesting Posts