首页 > 代码库 > 模拟MVC-WebForm实现ModelBinding
模拟MVC-WebForm实现ModelBinding
(一) 前言
用ASP.NET MVC的时候,我们都知道在提交表单的时候可以自动模型绑定到对应的实体上,这样开发者就不需要手动将表单数据转换成对应的model了。
然而,在WebForm中没有提供现成的方法让我们自动绑定模型,所以,我就通过反射写了一个泛型方法进行自动的模型绑定,同时还提供基本的数据验证。
(二) 编写ModelBinding方法
我们在BasePage类(此类继承自System.Web.UI.Page)中编写ModelBing方法。
代码如下:
1 #region 模型绑定 2 //模型绑定的错误消息 3 public Dictionary<string, string> ErrorMsgs = new Dictionary<string, string>(); 4 //是否验证通过 5 public bool IsValidated { get; set; } 6 /// <summary> 7 /// 手写模型绑定器--添加编辑数据时使用--对数据的验证不是很精确,主要还要依赖前台验证 8 /// </summary> 9 /// <typeparam name="T"></typeparam> 10 /// <returns></returns> 11 public T ModelBinding<T>(params T[] entityP) 12 { 13 14 object entity = Activator.CreateInstance(typeof(T));//添加 15 if (entityP != null && entityP.Length > 0)//编辑 16 { 17 entity = entityP[0]; 18 } 19 Type types = entity.GetType(); 20 var pros = types.GetProperties(); 21 Dictionary<string, System.Reflection.PropertyInfo> proNames = new Dictionary<string, System.Reflection.PropertyInfo>(); 22 foreach (var p in pros) 23 { 24 proNames.Add(p.Name, p); 25 } 26 var forms = Request.Form; 27 var keys = forms.AllKeys; 28 foreach (var key in keys) 29 { 30 if (proNames.Keys.Contains(key)) 31 { 32 var pro = proNames[key]; 33 var type = pro.PropertyType; 34 var columnValue =http://www.mamicode.com/ forms[key]; 35 if (string.IsNullOrEmpty(columnValue))//数据表列值不为空 36 { 37 continue; 38 } 39 try 40 { 41 if (type.IsEnum)//若果属性是枚举类型 42 { 43 pro.SetValue(entity, Enum.ToObject(type, columnValue), null); 44 } 45 else 46 { 47 if (type.IsGenericType && type.Name.StartsWith("Nullable"))//泛型类型 48 { 49 type = Nullable.GetUnderlyingType(type); 50 } 51 pro.SetValue(entity, Convert.ChangeType(columnValue, type), null); 52 53 } 54 } 55 catch (Exception ex) 56 { 57 ErrorMsgs.Add(key, ex.Message); 58 } 59 } 60 } 61 IsValidated = ErrorMsgs.Count > 0 ? false : true; 62 return (T)entity; 63 } 64 #endregion
说明:上述代码利用反射、泛型实现了简单的模型绑定和数据非法性的验证。
其中,表单数据的name必须和数据库表对应的列名一致。
(三) 表单aspx页面的约束
说明:表单数据的验证先在前台通过validate.js验证一遍,然后在服务端再次自动验证一遍。
因为是模拟ASP.NET MVC进行的模型绑定,所以在此页面上就完全不需要服务端控件了,这也极大的提高服务器了性能。
表单页面代码如下:
1 <%@ Page Language="C#" AutoEventWireup="true" ValidateRequest="false" CodeFile="NoticeEdit.aspx.cs" Inherits="Information_NoticeEdit" %> 2 3 <!DOCTYPE html> 4 5 <html xmlns="http://www.w3.org/1999/xhtml"> 6 <head id="Head1" runat="server"> 7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 8 <title></title> 9 <%--基础样式--%> 10 <link rel="stylesheet" type="text/css" href="../Styles/admin-all.css" /> 11 <link rel="stylesheet" type="text/css" href="../Styles/base.css" /> 12 <link rel="stylesheet" type="text/css" href="../Styles/formui.css" /> 13 <link href="../Styles/ui-lightness/jquery-ui-1.8.22.custom.css" rel="stylesheet" /> 14 15 <script src="../Scripts/JQuery/jquery-1.7.2.min.js"></script> 16 <script src="../Scripts/JQuery/jquery-ui-1.8.22.custom.min.js"></script> 17 <%--表格特效--%> 18 <script src="../Scripts/tb.js"></script> 19 20 21 <!--JBOX弹出插件--> 22 <script src="../Scripts/JBox/jquery.jBox-2.3.min.js" type="text/javascript"></script> 23 <!--JBOX弹出插件样式--> 24 <link href="../Scripts/JBox/Skins/Blue/jbox.css" rel="stylesheet" type="text/css" /> 25 <!--JBOX全局默认值--> 26 <script src="../Scripts/JBox/i18n/jquery.jBox-zh-CN.js" type="text/javascript"></script> 27 28 <!--验证--> 29 <link href="../Scripts/validate/validate.css" rel="stylesheet" /> 30 <!--验证--> 31 <script src="../Scripts/validate/jquery.validate.js"></script> 32 <!--汉化验证信息--> 33 <script src="../Scripts/validate/messages_cn.js"></script> 34 <!--日期控件--> 35 <%--<script src="../Scripts/My97DatePicker/WdatePicker.js"></script>--%> 36 <%--kindeditor--%> 37 <link href="../Scripts/kindeditor-4.1.10/themes/default/default.css" rel="stylesheet" /> 38 <script src="../Scripts/kindeditor-4.1.10/kindeditor-min.js"></script> 39 <script src="../Scripts/kindeditor-4.1.10/lang/zh_CN.js"></script> 40 <script type="text/javascript"> 41 $(function () { 42 var vForm = $("#form1").validate({ 43 errorElement: "span", 44 rules: { 45 Title: {required:true,maxlength:64}, 46 Contents: {required:true,maxlength:64}, 47 AddUserName: {required:true,maxlength:16}, 48 FromWhere: { required: true,maxlength:64 }, 49 Sort: {digits:true}, 50 Remark: { maxlength: 256 } 51 52 }, 53 messages: { 54 Title: {required:"必填信息",maxlength:"最大长度64"}, 55 Contents: {required:"必填信息",maxlength:"最大长度64"}, 56 AddUserName: {required:"必填信息",maxlength:"最大长度16"}, 57 FromWhere: {required:"必填信息",maxlength:"最大长度64"}, 58 Sort: {number:"必须是整数"}, 59 Remark: { maxlength: "最大长度256" } 60 61 } 62 }); 63 }) 64 65 var content = null; 66 KindEditor.ready(function (K) { 67 content = K.create("#Contents", { 68 cssPath: ‘../kindeditor-4.1.10/plugins/code/prettify.css‘, 69 uploadJson: ‘../kindeditor-4.1.10/asp.net/upload_json.ashx‘, 70 fileManagerJson: ‘../kindeditor-4.1.10/asp.net/file_manager_json.ashx‘, 71 allowFileManager: true, 72 afterCreate: function () { 73 this.sync(); 74 }, 75 afterBlur: function () { 76 this.sync(); 77 } 78 }); 79 prettyPrint(); 80 }); 81 82 </script> 83 84 </head> 85 <body> 86 <form id="form1" runat="server"> 87 <div class="alert alert-info">当前位置<b class=‘tip‘></b><%=ListTitle %></div> 88 <%-- 刷新返回--%> 89 <table class="tb"> 90 <tr height="45"> 91 <th> 92 <input type="button" class="btn" onclick=‘window.location.href=http://www.mamicode.com/window.location.href;‘ value="刷新" /> 93 94 <input type="button" class="btn" onclick=‘window.location.href="http://www.mamicode.com/<%=ListUrl %> ";‘ value="http://www.mamicode.com/返回" /> 95 </th> 96 </tr> 97 </table> 98 99 <%--表单--%> 100 <table class="tbform"> 101 <tbody> 102 103 <tr height="38"> 104 <td class="tdl" width="80">标题</td> 105 <td class="detail"> 106 <input type="text" id="Title" name="Title" value=‘<%=entity.Title %>‘ class="required width300 " /> 107 </td> 108 </tr> 109 <tr height="38"> 110 <td class="tdl">内容</td> 111 <td class="detail"> 112 <textarea name="Contents" id="Contents" style="width:670px;height:350px;visibility:hidden;" ><%=entity.Contents %></textarea> 113 </td> 114 </tr> 115 <tr height="38"> 116 <td class="tdl">作者</td> 117 <td class="detail"> 118 <input type="text" id="AddUserName" name="AddUserName" value=‘<%=entity.AddUserName %>‘ class="required width300" /> 119 </td> 120 </tr> 121 <tr height="38"> 122 <td class="tdl">来源</td> 123 <td class="detail"> 124 <input type="text" id="FromWhere" name="FromWhere" value=‘<%=entity.FromWhere %>‘ class="required width300" /> 125 </td> 126 </tr> 127 <tr height="38"> 128 <td class="tdl">排序</td> 129 <td class="detail"> 130 <input type="text" id="Sort" name="Sort" value=‘<%=entity.Sort==null?"50":entity.Sort.Value.ToString() %>‘ class="ipt width300" /> 131 </td> 132 </tr> 133 <tr height="38"> 134 <td class="tdl">备注</td> 135 <td class="detail"> 136 <textarea id="Remark" name="Remark" cols="48" rows="5"><%=entity.Remark %></textarea> 137 </td> 138 </tr> 139 </tbody> 140 </table> 141 142 <%--提交返回--%> 143 <table class="tb"> 144 <tr height="45"> 145 <th align="left"> 146 <input class="btn btn-success" id="find" type="submit" value="提交" /> 147 148 <input type="button" class="btn" onclick=‘window.location.href="http://www.mamicode.com/<%=ListUrl %> ";‘ value="http://www.mamicode.com/返回" /> 149 </th> 150 151 </tr> 152 </table> 153 <input type="hidden" id="hiddenId" name="hiddenId" value=‘<%=entity.Id==0?"":entity.Id.ToString() %>‘ /> 154 </form> 155 </body> 156 </html>
(四) 表单后台的自动添加修改
说明:由于是实现模型的自动绑定,所以就不能再手动的进行表单的组装了,通过下面可以看到,再也没有事件驱动了,表单数据也清爽了很多。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.UI; 6 using System.Web.UI.WebControls; 7 8 public partial class Information_NoticeEdit : WebBase.BasePage 9 { 10 protected string ListTitle = "信息管理<b class=‘tip‘></b>公告编辑"; 11 protected string EditUrl = "NoticeEdit.aspx"; 12 protected string ListUrl = "NoticeList.aspx"; 13 protected BLL.Info_NoticeBLL bll = BLL.BLLSession.Info_NoticeBLL;//当前数据访问网关 14 protected Model.Info_Notice entity = null; 15 protected void Page_Load(object sender, EventArgs e) 16 { 17 //权限验证 18 CheckUserPermission("NoticeManager", WebBase.BaseEnum.ActionEnum.View); 19 if (!IsPostBack) 20 { 21 LoadData(); 22 } 23 else 24 { 25 if (!string.IsNullOrEmpty(GetFormString("hiddenId"))) 26 { 27 ModifyData(); 28 } 29 else 30 { 31 AddData(); 32 } 33 } 34 } 35 36 //修改时加载数据 37 protected void LoadData() 38 { 39 entity = bll.GetEntityById(GetQueryInt("id")); 40 if (entity == null) 41 { 42 entity = new Model.Info_Notice(); 43 } 44 45 } 46 47 //添加数据 48 protected void AddData() 49 { 50 //添加时,模型绑定 51 entity = ModelBinding<Model.Info_Notice>(); 52 entity.AddUser = GetUser().Id; 53 entity.AddTime = DateTime.Now; 54 entity.Deleted = false; 55 56 if (IsValidated&&bll.AddEntity(entity)) 57 { 58 ShowJbox("添加成功", ListUrl, "success"); 59 } 60 else 61 { 62 ShowJbox("添加失败", "error"); 63 } 64 65 } 66 //修改数据 67 protected void ModifyData() 68 { 69 entity = bll.GetEntityById(GetFormInt("hiddenId")); 70 //修改时,模型绑定 71 entity = ModelBinding<Model.Info_Notice>(entity); 72 entity.ModUser = GetUser().Id; 73 entity.ModTime = DateTime.Now; 74 if (IsValidated && bll.ModifyEntity(entity)) 75 { 76 ShowJbox("修改成功", ListUrl, "success"); 77 } 78 else 79 { 80 ShowJbox("修改失败", "error"); 81 } 82 } 83 }
(五) 运行演示
1.列表页面如下:
2.添加编辑页面如下:
3.添加 成功如图:
(六) 小结
以上叙述,就完成了在webform中的模型绑定功能的实现。如有错误或者不妥之处,欢迎指正。