MVC3 ModelClientValidationRule比较2个不同的字段。 向两者添加必需的标志

我正在尝试使用IClientValidatable创建自定义validation

我有2个字段PhoneNumber和Mobile。 我希望用户中的一个或两个。 只需要1个,但必须至少提供一个。

到目前为止,我已经成功实现了这一目标

  public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { var rule = new ModelClientValidationRule { ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()), ValidationType = "required", }; rule.ValidationParameters.Add("phone", "PhoneNumber"); rule.ValidationParameters.Add("mobile", "MobileNumber"); yield return rule; } 

这将validation应用于输出的html元素

   

现在我知道并非一切都已完成。 但如果我尝试点击提交按钮,则validation会在我的摘要中显示2个validation错误。

我有点坚持如何添加validation器适配器。

到目前为止……我知道它的错误但是

  jQuery.validator.unobtrusive.adapters.add('required', [$("#PhoneNumber").val(), $("#MobileNumber").val()], function(options) { options.rules['required'] = options.params; options.messages['required'] = options.message; }); 

首先,您需要以与Compare属性类似的方式创建自己的validation属性 。

在此属性中,您将指定其他依赖属性,并且将格式化错误消息以考虑属性显示名称。

该属性将如下所示(我对其名称和默认错误消息并不感到骄傲!):

 public class SelectOneValidationAttribute : ValidationAttribute, IClientValidatable { private const string DefaultErrorMessage = "Please enter '{0}' or '{1}'."; private string _otherFieldName; public SelectOneValidationAttribute(String otherFieldName) : base(DefaultErrorMessage) { _otherFieldName = otherFieldName; } public override string FormatErrorMessage(string name) { return String.Format(CultureInfo.CurrentCulture, ErrorMessageString, name, _otherFieldName); } protected override DataAnnotationsValidationResult IsValid(object value, ValidationContext validationContext) { PropertyInfo otherPropertyInfo = validationContext.ObjectType.GetProperty(_otherFieldName); if (otherPropertyInfo == null) { return new DataAnnotationsValidationResult("Unknown property " + _otherFieldName); } string strValue = value == null ? null : value.ToString(); if(!String.IsNullOrEmpty(strValue)) //validation succeeds as this field has been populated return null; object otherPropertyValue = otherPropertyInfo.GetValue(validationContext.ObjectInstance, null); string strOtherPropertyValue = otherPropertyValue == null ? null : otherPropertyValue.ToString(); if (!String.IsNullOrEmpty(strOtherPropertyValue)) //validation succeeds as the other field has been populated return null; else //validation failed, none of the 2 fields were populated return new DataAnnotationsValidationResult(DefaultErrorMessage); } //Create the data attributes for the client to use public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { var rule = new ModelClientValidationRule { ValidationType = "selectone", ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()) }; rule.ValidationParameters["otherfield"] = FormatPropertyForClientValidation(_otherFieldName); yield return rule; } public static string FormatPropertyForClientValidation(string property) { return "*." + property; } } 

因此,您可以在模型中使用它,如:

 public class YourModel { [SelectOneValidation("Phone")] public string Mobile { get; set; } [SelectOneValidation("Mobile")] public string Phone { get; set; } } 

使用该代码,错误消息“请输入’移动’或’手机’。” 和“请输入’手机’或’手机’。” 服务器端validation失败时将显示。 (您可以在两者上设置相同的错误消息,例如“请输入一个……”)

为了添加客户端validation,您需要为不引人注意的validation创建适配器。 (确保在不显眼的validation解析文档之前将其添加到某处,否则您将需要手动解析它):

 //Add an adaptor for our new jquery validator, that builds the optional parameters //for our validation code (the other field to look at) $.validator.unobtrusive.adapters.add("selectone", ["otherfield"], function (options) { var prefix = getModelPrefix(options.element.name), other = options.params.otherfield, fullOtherName = appendModelPrefix(other, prefix), element = $(options.form).find(":input[name=" + fullOtherName + "]")[0]; setValidationValues(options, "selectone", element); }); 

这是使用在不显眼的validation库中定义的一些实用程序函数,如:

 function setValidationValues(options, ruleName, value) { options.rules[ruleName] = value; if (options.message) { options.messages[ruleName] = options.message; } } function getModelPrefix(fieldName) { return fieldName.substr(0, fieldName.lastIndexOf(".") + 1); } function appendModelPrefix(value, prefix) { if (value.indexOf("*.") === 0) { value = value.replace("*.", prefix); } return value; } 

最后,我创建了一个新的validation规则。 这是因为尽管所需的validation允许设置过滤表达式,因此当该表达式被评估为true时,该字段仅被标记为有效,请参阅必需的validation ,我们需要对onBlurvalidation应用类似的修复而不是等于规则。

validation方法是从等于validation应用所述修复,然后在另一个相关字段上使用依赖选择器调用所需规则,因此仅当字段为空且尚未填充依赖项时,所需validation才返回false。

 $.validator.addMethod("selectone", function (value, element, param) { // bind to the blur event of the target in order to revalidate whenever the target field is updated // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead var otherField = $(param); if (this.settings.onfocusout) { otherField.unbind(".validate-selectone").bind("blur.validate-selectone", function () { $(element).valid(); }); } var otherFieldBlankFilter = ":input[name=" + otherField[0].name + "]:blank"; return $.validator.methods.required.call(this, value, element, otherFieldBlankFilter); }); 

如果您不介意这一点,就好像您只在提交表单时进行validation,您可以编写一个直接使用所需规则的适配器:

 $.validator.unobtrusive.adapters.add("selectone", ["otherfield"], function (options) { var prefix = getModelPrefix(options.element.name), other = options.params.otherfield, fullOtherName = appendModelPrefix(other, prefix), element = $(options.form).find(":input[name=" + fullOtherName + "]")[0]; setValidationValues(options, "required", ":input[name=" + fullOtherName + "]:blank"); }); 

完成所有这些后,您的validation应该有效。 如果两者都为空并且您尝试提交,则将显示两个字段的错误消息。 如果您随后在其中一个中输入内容并标签,则应删除这两个错误消息。

您还应该能够根据需要进行调整,因为您可以修改validation属性,不显眼的适配器和validation规则。