回顾
《前端基于easyui的mvc扩展》、《前端基于easyui的mvc扩展(续)》前两篇介绍了mvc内如何基于easyui进行扩展,在mvc里面有很多简化的语法可以让开发人员快速开发,既然我们已经对mvc进行了扩展,那么当然也不能漏掉了基础的web form了。首先我们来比较一下mvc和web form,如果前端不使用razor,都是用aspx页面的话,使用的语法是一样的,只是mvc内提供了HtmlHelper、Model、ViewData等来简化开发。
也就是说,如果我们使用如下的方式,其实在web form里面也是可行的,但是与mvc不同的是,web form内并没有像HtmlHelper的对象可以直接进行扩展,因此我们只能重新创建一个类来实现这些功能,既然无法使用类似HtmlHelper的对象扩展,那么model对象也就必须在编码标签的时候手动传入了,大致代码如下:
<% User user = new User { Name = "测试", StateId = 2 }; %> <%=EasyUIHelper.ValidateText(u => u.Name, user)%> <%=EasyUIHelper.Datebox(u => u.Name, user)%>
<%=EasyUIHelper.Combobox<User>(u => u.StateId, user, "States", "{ id: 'myCob', 'data-options': ' 100, editable: false' }")%>
实现
那么要达到以上的效果其实也不难,因为我们在前两篇已经进行了实现了,只要将其重构一下,使其可以支持在web form内工作便可以了,那么首先我们遇到的问题便是如何把表达式树转化为属性,这个主题我在《获取Lambda表达式内表达式的值》该文章中已经进行了讲解,调整后代码大致如下:
public static string ValidateText<TModel>(Expression<Func<TModel, object>> expression, TModel model, string attributeJson, Dictionary<string, string> attributes) { string propertyName = PropertyHelper.ResloveName(expression);//关于获取表达式值的文章 PropertyInfo property = typeof(TModel).GetProperty(propertyName); TagBuilder tag = new TagBuilder("input"); //增加name、type属性 ValidationAttribute[] validationAttrs; if (property.TryGetAttributes(out validationAttrs)) { //请阅读转换规则代码 } var extraAttributes = string.IsNullOrEmpty(attributeJson) ? attributes : JsonHelper.Deserialize<IDictionary<string, string>>(attributeJson);//基于Newtonsoft转化json的公用方法 //添加属性 return tag.ToString(); }
这样前端的代码就顺利转换完成了,剩下的便是如何让表单提交到服务端后,怎么样进行验证呢,大概的流程如下:
- 将提交到服务端的表单直接转化为对应的实体类
- 读取实体类各个属性以及属性内的验证特性,一一进行进行验证
- 如果中间没有验证失败的话,那么就说明实体是符合验证要求的,可进行其他操作
第一步其实就是利用反射将属性相对应的值一一赋值给相应的属性而已,这里我们就不重复去实现了。
获取属性验证特性,我们可以通过扩展MemberInfo(因为PropertyInfo和MethodInfo都是MemberInfo的派生类)来获取特性,大致代码如下:
public static bool TryGetAttributes(this MemberInfo member, out TAttribute[] attributes, bool inherit = false) where TAttribute : Attribute { attributes = null; var objs = member.GetCustomAttributes(typeof(TAttribute), inherit); if (objs.Length == 0) return false; attributes = Array.ConvertAll(objs, obj => obj as TAttribute); return true; }
对验证特性进行验证的代码大致如下:
//遍历属性 ValidationAttribute[] validationAttributes = //获取验证特性 foreach (var validation in validationAttributes) { if (validation is RegularExpressionAttribute) { var regularAttr = validation as RegularExpressionAttribute; var reg = new Regex(regularAttr.Pattern); if (value != null && !reg.IsMatch(value.ToString())) return false; } else { ValidationResult result = validation.GetValidationResult(value, new ValidationContext(instance, null, null)); if (result != ValidationResult.Success) return false; } }
这里之所以要将RegularExpressionAttribute单独抽出来判断是因为System.ComponentModel.DataAnnotations.dll(v4.0.0.0)内的实现有BUG,没有根据正则正确的实现GetValidationResult方法。
效果
//实体 public class User { private string m_Name = null; [Required(ErrorMessage = "用户名不能为空!")] [StringLength(10, MinimumLength = 4, ErrorMessage = "用户名长度必须在4-10之间")] [DisplayName("用户名:")] public string Name { get { return m_Name; } set { m_Name = value; } } //略 } //前端 <% FormBuilder form = new FormBuilder(); User user = new User { Name = "测试", StateId = 2 }; %> <%=form.CreateBeginHtml("/Handlers/MvcHandler.ashx", "fmTest")%> <%=EasyUIHelper.ValidateText(u => u.Name, user)%> <br /> <%=EasyUIHelper.Combobox(u => u.StateId, user, "States", "{ id: 'myCob', 'data-options': ' 100, editable: false'}")%> <br /> <input type="submit" value="提交" /> <%=form.CreateEndHtml() %> <script type="text/javascript"> $('#fmTest').easyuiForm(); </script>
结尾
谢谢大家,如文章有任何问题和错误请指出,谢谢!