背景
由於MVC的前端是基於jquery.validate和jquery.validate.unobtrusive來實現的,但是當我們要使用其他的ui組件且組件本身就帶有完整的驗證功能的話,那么要讓它們配合起來是有些麻煩的,比如:easyui。
介紹
MVC主要提供了一下幾個驗證特性來支撐前端的驗證:
- CustomValidationAttribute:指定一個用於驗證目標成員的驗證類型和驗證方法。
- DataTypeAttribute:指定要與數據字段關聯的附加類型的名稱。
- RangeAttribute:用於驗證數值字段的值是否在指定的范圍之內。
- RegularExpressionAttribute:用於驗證字符串字段的格式是否與指定的正則表達式相匹配。
- RequiredAttribute:用於驗證必需數據字段。
- StringLengthAttribute:用於驗證目標字段的字符串長度是否在指定的范圍之內。
- CompareAttribute:用於驗證目標字段的值是否與另一個字段值一致,在用戶注冊場景中可以用於確認兩次輸入密碼的一致性。
- RemoteAttribute:提供使用 jQuery 驗證插件遠程驗證程序的特性。
以上大部分來自System.ComponentModel.DataAnnotations.dll,最后2個是來自System.Web.Mvc.dll
而easyui則是基於validatebox可自定義驗證規則以及派生出datebox、numberbox、combobox等控件,來實現form表單輸入控件的一套完成的驗證體系(詳情可參考:www.jeasyui.com),easyui的驗證代碼如下:
<input class="easyui-validatebox validatebox-text" name="Name" required="true" missingmessage="用戶名不能為空!" validtype="regular['^\\w+$', '用戶名格式不正確!']" value="admin" type="text">
實現
了解了以上的2方提供的驗證支持,那么我們就可以將mvc提供的驗證解析為支持easyui驗證的前端html代碼了,根據以上的資料我們可以發現以下幾個可直接轉換的規則,實現代碼大致如下:
var attribute = validationAttrs.FirstOrDefault(attr => attr is RequiredAttribute); if (attribute != null) { tag.AddAttribute("required", "true"); tag.AddAttribute("missingMessage", attribute.ErrorMessage); } attribute = validationAttrs.FirstOrDefault(attr => !(attr is RequiredAttribute)); if (attribute == null) return; if (attribute is StringLengthAttribute) { var stringLengthAttr = attribute as StringLengthAttribute; tag.AddAttribute("invalidMessage", stringLengthAttr.ErrorMessage); tag.AddAttribute("validType", "length[{0}, {1}]", stringLengthAttr.MinimumLength, stringLengthAttr.MaximumLength); } else if (attribute is RegularExpressionAttribute) { var regularAttr = attribute as RegularExpressionAttribute; tag.AddAttribute("validType", "regular['{0}', '{1}']", regularAttr.Pattern.Replace("\\", "\\\\"), regularAttr.ErrorMessage); } else if (attribute is RangeAttribute) { var rangeAttr = attribute as RangeAttribute; tag.AddAttribute("validType", "range[{0}, {1}, '{2}']", rangeAttr.Minimum, rangeAttr.Maximum, rangeAttr.ErrorMessage); } else if (attribute is CompareAttribute) { var compareAttr = attribute as CompareAttribute; tag.AddAttribute("validType", "eq['[name={0}]', '{1}']", compareAttr.OtherProperty, compareAttr.ErrorMessage); }
以上代碼中把RequiredAttribute和其他的驗證規則區分開來是因為RequiredAttribute會生成獨立的required="true",而其他的驗證規則都是公用validType屬性的,至於js驗證規則內的regular、range、eq的驗證規則並不是easyui內部提供的,而是額外進行擴展的,js代碼如下:
$.extend($.fn.validatebox.defaults.rules, { eq: { validator: function (value, param) { this.message = param[1]; return value == $(param[0]).val(); } }, range: { validator: function (value, param) { this.message = param[2]; return value >= param[0] && value <= param[1]; } }, regular: { validator: function (value, param) { this.message = param[1]; var reg = new RegExp(param[0]); return reg.test(value); } } });
有了以上這些生成規則以后,我們就可以通過擴展HtmlHelper<TModel>來實現類似@Html.EditorFor(model => model.Name)這樣的調用了,大致代碼如下(這里以validatebox為例):
public static MvcHtmlString ValidateText(this HtmlHelper htmlHelper, Expression<Func<TModel, object>> expression) { ModelMetadata modelMetadatum = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); PropertyInfo property = typeof(TModel).GetProperty(modelMetadatum.PropertyName); TagBuilder tag = new TagBuilder("input"); ValidationAttribute[] validationAttrs; if (property.TryGetAttributes(out validationAttrs)) { //請閱讀轉換規則代碼 } return MvcHtmlString.Create(tag.ToString()); }
有了以上基礎代碼之后,我們就可以使用@Html.ValidateText(m => m.Name)來創建基於easyui的驗證控件了。
效果
//類: public class AccountView { private string m_Name = null; [Required(ErrorMessage = "用戶名不能為空!")] [RegularExpression(@"^\w+$", ErrorMessage = "用戶名格式不正確!")] [DisplayName("用戶名:")] public string Name { get { return m_Name; } set { m_Name = value; } } } //頁面: @Html.LabelFor(m => m.Name) @Html.ValidateText(m => m.Name)//生成的內容為頂部easyui html示例代碼
正確:
必填提示:
驗證失敗:
結尾
以上便是今天所有內容了,后面還有其他的擴展功能,敬請期待,謝謝各位!