客户端列表的MVC自定义validation

我正在尝试编写一个在客户端工作的自定义validation器,validation所有复选框都已勾选。

这是模型上的声明:

[DeclarationsAccepted(ErrorMessage = "You must tick all declarations")] public IList DeclarationQuestions { get; set; } 

这是属性:

 public class DeclarationsAccepted : ValidationAttribute, IClientValidatable { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { var questions = value as IList; if (questions != null && questions.All(c => c.Answer)) { return ValidationResult.Success; } return new ValidationResult("You must accepted all declarations to continue"); } public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { var modelClientValidationRule = new ModelClientValidationRule { ValidationType = "declarationsaccepted", ErrorMessage = FormatErrorMessage(metadata.DisplayName) }; yield return modelClientValidationRule; } } 

到目前为止这么好,工程服务器端。

对于客户端,我按如下方式连接:

 jQuery.validator.addMethod('declarationsaccepted', function (value, element, params) { //Implement logic here to check all boxes are ticked console.log(value); return false; }, ''); jQuery.validator.unobtrusive.adapters.add('declarationsaccepted', {}, function (options) { options.rules['declarationsaccepted'] = true; options.messages['declarationsaccepted'] = options.message; }); 

我正在显示如下的复选框:

 @{ var questionIndex = 0; } @foreach (var question in Model.DeclarationQuestions) { @Html.CheckBoxFor(model => Model.DeclarationQuestions[questionIndex].Answer, new { id = "DeclarationQuestions" + questionIndex}) questionIndex++; } 

然后使用以下方法显示validation消息:

 @Html.ValidationMessageFor(c => c.DeclarationQuestions) 

当我提交表单时,会显示消息,但只有在回发到服务器后才会显示。 有没有办法让这个在客户端工作?

您不会获得客户端validation的原因是因为html帮助程序为与属性关联的控件生成data-val-*属性。 jquery.validate.unobtrusive在解析表单时使用规则读取这些属性,在与该控件关联的ValidationMessageFor()生成的相应元素中显示错误消息(它通过匹配元素的id属性来实现此错误 – 错误消息是在的范围内生成的。

您不能(并且无法)为属性DeclarationQuestions生成控件(仅适用于DeclarationQuestions中每个项目的属性,因此没有任何内容可以匹配。

您可以通过包含自己的错误消息占位符和拦截.submit事件来处理此问题

html(将css添加到样式#conditions-error as display:none;

  You must accept all declarations to continue.  

脚本

 var declarationsError = $('#delarations-error'); $('form').submit(function() { var isValid = $('.yourCheckBoxClass').not(':checked') == 0; if(!isValid) { declarationsError.show(); // display error message return false; // prevent submit } }); $('.yourCheckBoxClass').change(function() { if($(this).is(':checked')) { declarationsError.hide(); // hide error message } }); 

旁注:你应该循环生成复选框

 for (int i = 0; i < Model.DeclarationQuestions.Count; i++) { @Html.CheckBoxFor(m => m.DeclarationQuestions[i].Answer, new { id = "DeclarationQuestions" + i}) }