[转载]ASP.NET MVC中对Model进行多步验证的解决方法 – 海纳百川 – 博客园.
在我之前的博文:ASP.NET MVC2.0结合WF4.0实现用户多步注册流程中 将一个用户的注册分成了四步,而这四个步骤都是对一个Model操作的。当时我加上ModelState.IsValid这句验证代码的时候,根本没法通 过验证,因为在注册的前面三步,注册用户的Model信息都没填写完整。当时很纠结,因为刚接触ASP.NET MVC,故没有找到解决方案。我想现在给出解决的办法也为时不晚。看下面需要验证的Model的代码如下:
public class UserViewModel { [DisplayName("step")] [Required(ErrorMessage = "You must select a step .")] public int Step { get; set; } //个人信息 [Required(ErrorMessage = "姓名不能为空")] [StringLength(20, ErrorMessage = "姓名长度不能超过20个字符")] public string Name { get; set; } [RegularExpression(@"120|((1[0-1]|\d)?\d)", ErrorMessage = "年龄格式不对")] public int? Age { get; set; } //职位信息 [Required(ErrorMessage = "职位不能为空")] public string Post { get; set; } public int? Salary { get; set; } //学历信息 [Required(ErrorMessage = "毕业院校不能为空")] public string University { get; set; } public int? GraduationYear { get; set; } //联系信息 [Required(ErrorMessage = "邮件不能为空")] [RegularExpression(@"^[a-z][a-z|0-9|]*([_][a-z|0-9]+)*([.][a-z|" + @"0-9]+([_][a-z|0-9]+)*)?@[a-z][a-z|0-9|]*\.([a-z]" + @"[a-z|0-9]*(\.[a-z][a-z|0-9]*)?)$", ErrorMessage= "邮件格式不正确")] public string Email { get; set; } public int? Mobile { get; set; } public IEnumerable<SelectListItem> StepList { get; set; } public UserViewModel() { var list = new List<SelectListItem>() { new SelectListItem { Text = "(Select)" }, new SelectListItem { Value = "1", Text = "Step1" }, new SelectListItem { Value = "2", Text = "Step2" }, new SelectListItem { Value = "3", Text = "Step3" }, new SelectListItem { Value = "4", Text = "Step4" } }; this.StepList = new SelectList(list, "Value", "Text"); } }
实现:
这篇文章这种情况服务端和客户端的验证都会讲到。为了简化起见,这里我除去的WF的流程功能,直接用下拉框表示,当下拉框选择step1表示填写第一步注 册的信息,当下拉框选择step2表示填写第二步注册的信息,当下拉框选择step3表示填写第三步注册的信息,当下拉框选择step4表示填写第四步注 册的信息。这个很容易实现,我使用JQuery来显示和隐藏下拉框对应的step,JQuery代码如下:
<script type="text/javascript"> $(function () { $.fn.enable = function () { return this.show().removeAttr("disabled"); } $.fn.disable = function () { return this.hide().attr("disabled", "disabled"); } var dllStep = $("#Step"); var step1 = $("#Step1,#Step1 input"); var step2 = $("#Step2,#Step2 input"); var step3 = $("#Step3,#Step3 input"); var step4 = $("#Step4,#Step4 input"); setControls(); dllStep.change(function () { setControls(); }); function setControls() { switch (dllStep.val()) { case "1": step1.enable(); step2.disable(); step3.disable(); step4.disable(); break; case "2": step1.disable(); step2.enable(); step3.disable(); step4.disable(); break; case "3": step1.disable(); step2.disable(); step3.enable(); step4.disable(); break; case "4": step1.disable(); step2.disable(); step3.disable(); step4.enable(); break; case "": step1.disable(); step2.disable(); step3.disable(); step4.disable(); break; } } }); </script>
如下图:
第一步:填写姓名和年龄。
第二步:填写职位和薪水
第三步填写:毕业院校和毕业时间
第四步填写:邮箱和电话
为了实现这样的验证,我们可以将验证的错误信息中移除不在当前步骤填写的字段的错误信息,写一个类InputValidationModelBinder 继承DefaultModelBinder并重载OnModelUpdated方法,将不必要的错误信息清除,代码如下:
public class InputValidationModelBinder : DefaultModelBinder { protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) { var modelState = controllerContext.Controller.ViewData.ModelState; var valueProvider = controllerContext.Controller.ValueProvider; var keysWithNoIncomingValue = modelState.Keys.Where(x => !valueProvider.ContainsPrefix(x)); foreach (var key in keysWithNoIncomingValue) modelState[key].Errors.Clear(); } }
上面是服务端的代码,对于客户端,我们都知道ASP.NET MVC客户端验证时通过MicrosoftMvcValidation.js去实现的。看下面代码。
1 validate: function Sys_Mvc_FormContext$validate(eventName) { 2 var fields = this.fields; 3 var errors = []; 4 for (var i = 0; i < fields.length; i++) { 5 var field = fields[i]; 6 if (!field.elements[0].disabled) { 7 var thisErrors = field.validate(eventName); 8 if (thisErrors) { 9 Array.addRange(errors, thisErrors); 10 } 11 } 12 } 13 if (this.replaceValidationSummary) { 14 this.clearErrors(); 15 this.addErrors(errors); 16 } 17 return errors; 18 } 19 }
在第6行代码加入了一句判断:当页面的元素没有被disabled的时候才验证。
好了这样就实现了一次只对Model中的几个属性字段进行验证。
运行:
ASP.NET mvc的验证机制只对model中当前页面的属性进行验证:
填写正确通过验证:
总结: