MVC3不显眼的validation组input

我需要validation3个或更多的input字段(至less需要一个)。 例如,我有电子邮件,传真,电话。

我需要至less一个填写。我需要服务器和客户端“不显眼的validation”。 请帮忙。 我看着“比较”的方法,并尝试修改它,但没有运气。 请帮忙。 谢谢

你可以写一个自定义属性:

public class AtLeastOneRequiredAttribute : ValidationAttribute, IClientValidatable { private readonly string[] _properties; public AtLeastOneRequiredAttribute(params string[] properties) { _properties = properties; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { if (_properties == null || _properties.Length < 1) { return null; } foreach (var property in _properties) { var propertyInfo = validationContext.ObjectType.GetProperty(property); if (propertyInfo == null) { return new ValidationResult(string.Format("unknown property {0}", property)); } var propertyValue = propertyInfo.GetValue(validationContext.ObjectInstance, null); if (propertyValue is string && !string.IsNullOrEmpty(propertyValue as string)) { return null; } if (propertyValue != null) { return null; } } return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); } public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { var rule = new ModelClientValidationRule { ErrorMessage = ErrorMessage, ValidationType = "atleastonerequired" }; rule.ValidationParameters["properties"] = string.Join(",", _properties); yield return rule; } } 

这可以用来装饰你的视图模型属性之一(如果validation失败,你想要突出显示的属性):

 public class MyViewModel { [AtLeastOneRequired("Email", "Fax", "Phone", ErrorMessage = "At least Email, Fax or Phone is required")] public string Email { get; set; } public string Fax { get; set; } public string Phone { get; set; } } 

然后一个简单的控制器:

 public class HomeController : Controller { public ActionResult Index() { var model = new MyViewModel(); return View(model); } [HttpPost] public ActionResult Index(MyViewModel model) { return View(model); } } 

呈现下面的视图,它将负责定义自定义客户端validation器适配器:

 @model MyViewModel <script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script> <script type="text/javascript"> jQuery.validator.unobtrusive.adapters.add( 'atleastonerequired', ['properties'], function (options) { options.rules['atleastonerequired'] = options.params; options.messages['atleastonerequired'] = options.message; } ); jQuery.validator.addMethod('atleastonerequired', function (value, element, params) { var properties = params.properties.split(','); var values = $.map(properties, function (property, index) { var val = $('#' + property).val(); return val != '' ? val : null; }); return values.length > 0; }, ''); </script> @using (Html.BeginForm()) { @Html.ValidationSummary(false) <div> @Html.LabelFor(x => x.Email) @Html.EditorFor(x => x.Email) </div> <div> @Html.LabelFor(x => x.Fax) @Html.EditorFor(x => x.Fax) </div> <div> @Html.LabelFor(x => x.Phone) @Html.EditorFor(x => x.Phone) </div> <input type="submit" value="OK" /> } 

当然,自定义适配器和validation器规则应该外部化为一个单独的JavaScript文件,以避免混合脚本和标记。

我花了超过36小时,为什么代码不能为我工作..最后,我发现在我的情况下,我不应该使用这一行代码中的属性名称

 [AtLeastOneRequired("Email", "Fax", "Phone", ErrorMessage = "At least Email, Fax or Phone is required")] 

但是我不得不使用HTMl元素ID来代替属性名称,它的工作方式就像魔术一样。

在这里发布,如果这可能有助于某人。

由于您使用的是MVC 3,请查看Brad Wilson在mvcConf上的精彩video 。 有一切你需要创build客户端+服务器不显眼的validation

@Darin Kimitrov的解决scheme可能是创build自定义validation属性的标准,可以与不显眼的validation一起使用。 但是,使用自定义validation属性进行不显眼的validation有一些缺点,例如:

  • 自定义validation属性仅附加到一个属性,所以如果另外两个input发生更改事件,则客户端validation将不起作用。
  • 错误消息与ValidationSummary一起工作正常,但是如果你想要显示整个组的错误信息(我认为这是常态),那几乎是不可能的。
  • 为了避免第一个问题,我们可以将自定义validation属性添加到组中的每个元素,这将导致另一个问题:我们必须validation组的所有元素,而不是停在第一个无效的组元素。 当然,第二个问题 – 每个元素的单独错误消息仍然存在。

还有另一种方式来处理客户端input的validation,使用jqueryvalidation器( https://jqueryvalidation.org/validate/#groups )中的组设置。 唯一的问题是,不显眼的validation默认情况下不支持jQueryvalidation的组,所以我们必须自定义一些。

虽然这个答案很难“不显眼”,但在我看来,如果你的最终目标是在使用微软的不显眼的validation器库的同时validation一组input,那么值得尝试摆脱不必要的代码复杂性。

首先,因为默认的jQueryvalidation器的组设置不可用jQuery的不显眼的validation,我们必须重写不显眼的设置(参考。 我如何定制ASP.NET MVC 3中的不显眼的validation,以匹配我的风格?

 $("form").on('submit', function () { var form = this; var validator = $(this).data("validator"); if (validator.settings && !validator.settings.submitHandler) { $.extend(true, validator.settings.rules, validationSettings.rules); $.extend(true, validator.settings.groups, validationSettings.groups); initGroups(validator); var fnErrorReplacement = validator.settings.errorPlacement; validator.settings.errorPlacement = function (error, element) { validationSettings.errorPlacement(error, element, fnErrorReplacement, form); } validator.settings.submitHandler = formSubmitHandler; } }); function formSubmitHandler(form) { form.submit(); } 

之后,重写不显眼的validation器的组,规则和errorPlacement设置。

 var validationSettings = { groups: { checkboxgroup: "Email Fax Phone" }, rules: { Email: { required: function () { return validateCheckboxGroup(["#Email", "#Fax", "#Phone"]); } }, Fax: { required: function () { return validateCheckboxGroup(["#Email", "#Fax", "#Phone"]); } }, Phone: { required: function () { return validateCheckboxGroup(["#Email", "#Fax", "#Phone"]); } } } , errorPlacement: function (error, element, fnUnobtrusive, form) { switch (element.attr("name")) { case "Email": case "Fax": case "Phone": onGroupError(error, "CheckBoxGroup", form); break; default: fnUnobtrusive(error, element); break; } } } function validateCheckboxGroup(names) { var result = true; $.each(names, function (index, value) { if ($(value).is(":checked")) { result = false; } }); return result; } 

因为不显眼的validation器没有实现jqueryvalidation器的组设置,所以我们需要从两个库中重用两个函数:(1).split组名(从jqueryvalidation器重用代码)和(2)追加错误元素而不删除'input-validation错误“类(从不显眼的库重用函数onError)。

 function initGroups(validators) { validators.groups = {}; $.each(validators.settings.groups, function (key, value) { if (typeof value === "string") { value = value.split(/\s/); } $.each(value, function (index, name) { validators.groups[name] = key; }); }); } function onGroupError(error, inputElementName, form) { var container = $(form).find("[data-valmsg-for='" + inputElementName + "']"), replaceAttrValue = container.attr("data-valmsg-replace"), replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null; container.removeClass("field-validation-valid").addClass("field-validation-error"); error.data("unobtrusiveContainer", container); if (replace) { container.empty(); error.appendTo(container); } else { error.hide(); } } 

最后,使用HtmlExtensions.ValidationMessage创buildcheckbox组的错误跨度。

 @Html.ValidationMessage("CheckBoxGroup", new { @class = "text-danger" }) 

保持“inputvalidation错误”类是必要的,这样jqueryvalidation器将validationcheckbox组的所有3个元素(电子邮件,电话,传真)作为一个整体,而不是逐一validation。 不显眼的validation库默认在函数onError中删除这个类,所以我们必须在上面的函数onGroupError中将其定制为showne。

我在这里发布了一个类似于这个问题的答案 。 我的解决scheme是使用由查询validation团队创build的require_from_group (查看此文件夹 )方法的更加stream行的方式。

解决scheme是通用的,因为它适用于每种inputtypes, textareaselect 。 您还可以指定需要填写的validation字段的数量。

希望有所帮助!