本文繼續體驗自定義驗證規則,需求是禁止輸入某些值。本文與前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> }
效果: