首页 > 代码库 > 模拟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                     &nbsp;&nbsp;
 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                     &nbsp;&nbsp;
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>
aspx页面代码

 

(四) 表单后台的自动添加修改                                                    

说明:由于是实现模型的自动绑定,所以就不能再手动的进行表单的组装了,通过下面可以看到,再也没有事件驱动了,表单数据也清爽了很多。

 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中的模型绑定功能的实现。如有错误或者不妥之处,欢迎指正。