本文继续体验自定义验证规则,需求是禁止输入某些值。本文与前2篇相关,请参考:
MVC验证01-基础、远程验证
MVC验证02-自定义验证规则、邮件验证
自定义验证特性继承ValidationAttribute,并实现IClientValidatable接口
展开using System.ComponentModel.DataAnnotations; using System.Web.Mvc; namespace MvcValidation.Extension { /// <summary> /// 用来禁止属性某个值的输入 /// </summary> public sealed class NoInputAttribute : ValidationAttribute, IClientValidatable { public string Input { get; set; } public NoInputAttribute(string input) { this.Input = input; } public override bool IsValid(object value) { //如果没有输入值,放行 if (value == null) { return true; } if (value is string) { if (Input.Contains(value.ToString())) { return false; } } return true; } public System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { ModelClientValidationRule rule = new ModelClientValidationRule { ValidationType = "noinput", ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()) }; rule.ValidationParameters["input"] = Input; yield return rule; } } }
把自定义属性打到View model的属性上
展开public class RegisterModel { [Required] [StringLength(6, MinimumLength = 2)] //加 [Display(Name = "用户名")] [NoInput("demo",ErrorMessage = "不能使用此名称")] public string UserName { get; set; } [Required] [DataType(DataType.EmailAddress)] [Display(Name = "邮件")] public string Email { get; set; } [Required] [StringLength(100, ErrorMessage = "{0}栏位最少{2}个字,最多{1}个字", MinimumLength = 6)] [DataType(DataType.Password)] [Display(Name = "密码")] public string Password { get; set; } [DataType(DataType.Password)] [Display(Name = "确认密码")] [System.ComponentModel.DataAnnotations.Compare("Password", ErrorMessage = "密码和确认密码不匹配。")] public string ConfirmPassword { get; set; } }
[NoInput("demo",ErrorMessage = "不能使用此名称")],即当输入demo的时候就报错。
扩展jquery的验证方法jQuery.validator.noinput.js并注册
jquery的验证扩展方法的逻辑基本上与自定义特性IsValid()方法一致。
自定义特性rule.ValidationParameters["input"]的键input要传递给$.validator.unobtrusive.adapters.addSingleVal()方法。
展开//扩展的方法名与NoInputAttribute保持一致,且是小写 //value是指前端输入的值 //element是指html元素 //parm是指输入的参数,即rule.ValidationParameters["input"]键input对应的值,通过NoInputAttribute的构造函数注入的 $.validator.addMethod("noinput", function(value, element, param) { if (value == false) { //如果value没有输入,这里就放行 return true; } if (value.indexOf(param) != -1) { //如果前端输入的值value包含自定义验证特性NoInputAttribute的属性Input值,就不放行 return false; } else { return true; } }); //第一个参数就是jquery验证扩展方法名 //第二个参数就是rule.ValidationParameters["input"]的键 $.validator.unobtrusive.adapters.addSingleVal("noinput", "input");
Register.cshtml视图
展开@model MvcValidation.Models.RegisterModel @{ ViewBag.Title = "注册"; } <hgroup class="title"> <h1>@ViewBag.Title.</h1> <h2>创建新帐户。</h2> </hgroup> @using (Html.BeginForm()) { @Html.AntiForgeryToken() @Html.ValidationSummary() <fieldset> <legend>注册表单</legend> <ol> <li> @Html.LabelFor(m => m.UserName) @Html.TextBoxFor(m => m.UserName) </li> <li> @Html.LabelFor(m => m.Email) @Html.TextBoxFor(m => m.Email) </li> <li> @Html.LabelFor(m => m.Password) @Html.PasswordFor(m => m.Password) </li> <li> @Html.LabelFor(m => m.ConfirmPassword) @Html.PasswordFor(m => m.ConfirmPassword) </li> </ol> <input type="submit" value="注册" /> </fieldset> } @section Scripts { @Scripts.Render("~/bundles/jqueryval") <script src="~/Scripts/jQuery.validator.noinput.js"></script> }
效果:
如果需要禁止多个值,需要重写自定义验证特性
这时候自定义特性的Input属性类型变成了string[],因为要判断多个值。
但前台rule.ValidationParameters["input"]存储的应该是string类型,所以保存的时候要把Input数组元素join起来。
展开using System; using System.ComponentModel.DataAnnotations; using System.Web.Mvc; namespace MvcValidation.Extension { /// <summary> /// 用来禁止属性某个值的输入 /// </summary> public sealed class NoInputAttribute : ValidationAttribute, IClientValidatable { public string[] Input { get; set; } public NoInputAttribute(string input) { if (input.IndexOf(",") > -1)//如果输入的字符串有逗号分隔 { //把字符串分割成数组赋值给Input this.Input = input.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries); } else { //没有逗号,就构建一个数组赋值给Input this.Input = new string[]{input}; } } public override bool IsValid(object value) { //如果没有输入值,放行 if (value == null) { return true; } if (value is string) { if (string.Join(",", Input).Contains(value.ToString())) { return false; } } return true; } public System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { ModelClientValidationRule rule = new ModelClientValidationRule { ValidationType = "noinput", ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()) }; rule.ValidationParameters["input"] = string.Join(",", Input); yield return rule; } } }
把自定义属性打到View model的属性上,但构造函数是用逗号分隔的字符串
展开 public class RegisterModel { [Required] [StringLength(6, MinimumLength = 2)] //加 [Display(Name = "用户名")] [NoInput("demo,jack",ErrorMessage = "不能使用此名称")] public string UserName { get; set; } [Required] [DataType(DataType.EmailAddress)] [Display(Name = "邮件")] public string Email { get; set; } [Required] [StringLength(100, ErrorMessage = "{0}栏位最少{2}个字,最多{1}个字", MinimumLength = 6)] [DataType(DataType.Password)] [Display(Name = "密码")] public string Password { get; set; } [DataType(DataType.Password)] [Display(Name = "确认密码")] [System.ComponentModel.DataAnnotations.Compare("Password", ErrorMessage = "密码和确认密码不匹配。")] public string ConfirmPassword { get; set; } }
[NoInput("demo,jack",ErrorMessage = "不能使用此名称")],当输入demo或者jack的时候都会报错。
扩展jquery的验证方法jQuery.validator.noinput1.js并注册
需要把rule.ValidationParameters["input"]存储的值split成数组,在遍历判断。
展开//扩展的方法名与NoInputAttribute保持一致,且是小写 //value是指前端输入的值 //element是指html元素 //parm是指输入的参数,即rule.ValidationParameters["input"]键input对应的值,通过NoInputAttribute的构造函数注入的 $.validator.addMethod("noinput", function (value, element, param) { if (value == false) { //如果value没有输入,这里就放行 return true; } var validateState = true; //param就是自定义特性rule.ValidationParameters["input"]对应的值 var paramarr = param.split(','); //第一个参数是数组元素的索引 //第二个参数是数组元素 $.each(paramarr, function(index, ele) { if (value == ele) { validateState = false; return; } }); return validateState; }); //第一个参数就是jquery验证扩展方法名 //第二个参数就是rule.ValidationParameters["input"]的键 $.validator.unobtrusive.adapters.addSingleVal("noinput", "input");
Register.cshmtl要引用jQuery.validator.noinput1.js
展开@model MvcValidation.Models.RegisterModel @{ ViewBag.Title = "注册"; } <hgroup class="title"> <h1>@ViewBag.Title.</h1> <h2>创建新帐户。</h2> </hgroup> @using (Html.BeginForm()) { @Html.AntiForgeryToken() @Html.ValidationSummary() <fieldset> <legend>注册表单</legend> <ol> <li> @Html.LabelFor(m => m.UserName) @Html.TextBoxFor(m => m.UserName) </li> <li> @Html.LabelFor(m => m.Email) @Html.TextBoxFor(m => m.Email) </li> <li> @Html.LabelFor(m => m.Password) @Html.PasswordFor(m => m.Password) </li> <li> @Html.LabelFor(m => m.ConfirmPassword) @Html.PasswordFor(m => m.ConfirmPassword) </li> </ol> <input type="submit" value="注册" /> </fieldset> } @section Scripts { @Scripts.Render("~/bundles/jqueryval") <script src="~/Scripts/jQuery.validator.noinput1.js"></script> }
效果: