背景
由於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示例代碼
正確:

必填提示:

驗證失敗:

結尾
以上便是今天所有內容了,后面還有其他的擴展功能,敬請期待,謝謝各位!
