背景
由于MVC的前端是基于jquery.validate和jquery.validate.unobtrusive来实现的,但是当我们要使用其他的ui组件且组件本身就带有完整的验证功能的话,那么要让它们配合起来是有些麻烦的,比如:easyui。
介绍
MVC主要提供了一下几个验证特性来支撑前端的验证:
以上大部分来自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示例代码
正确:
必填提示:
验证失败:
结尾
以上便是今天所有内容了,后面还有其他的扩展功能,敬请期待,谢谢各位!