1. 程式人生 > >MVC--DefaultModelBinder解析request參數

MVC--DefaultModelBinder解析request參數

cancel class 取消 += 英文 -- httppost mod spn

轉載:http://www.cnblogs.com/leotsai/p/ASPNET-MVC-DefaultModelBinder.html

看到很多ASP.NET MVC項目還在從request.querystring或者formContext裏面獲取數據,這實在是非常落後的做法。也有的項目建了大量的自定義的modelbinder,以為很牛,實際上也落後的很。

ASP.NET MVC提供了IModelBinder的默認實現,這個實現的類就叫DefaultModelBinder。我們在寫代碼的時候,幾乎感覺不到這個類的存在,因為這個類自動將request信息解析成action參數。本文將向大家展示這個類是多麽強大,可以拯救大量的代碼。

先看個例子。假如有如下表單,用於編輯用戶信息以及該用戶的時間表。在這個例子中,我要利用DefaultModelBinder自動將整個表單數據解析成復雜實體類的實例。一行手工解析的C#代碼都不用寫。

技術分享

對應的controller的代碼如下,很簡單:

 1 public class DemoController : PublicControllerBase
 2 {
 3     public ActionResult UserEditor()
 4     {
 5         return View();
 6     }
 7 
 8     [HttpPost]
 9     public
string SaveUser(DemoUser user) 10 { 11 var result = string.Empty; 12 if (user != null) 13 { 14 result = Serializer.ToJson(user); 15 } 16 return result; 17 } 18 }

相關的實體類的定義,也很簡單:

 1 public class DemoUser
 2 {
 3     public string Username { get
; set; } 4 public string Email { get; set; } 5 public string Language { get; set; } 6 public Gender Gender { get; set; } 7 public int[] RoleIds { get; set; } 8 public List<ScheduledJob> Jobs { get; set; } 9 } 10 11 public class ScheduledJob 12 { 13 public string Job { get; set; } 14 public string From { get; set; } 15 public string To { get; set; } 16 } 17 18 public enum Gender 19 { 20 Unknown = 0, 21 Male = 1, 22 Female = 2 23 }

請註意SaveUser這個action的參數,一個比較復雜的實體類的對象。DefaultModelBinder會自動將這個復雜的表單解析出來。這個保存的action將參數user直接序列化JSON字符串返回到瀏覽器。

下面看看HTML和JS。

HTML:

 1 <form id="formUserEditor" action="/demo/saveuser" method="POST">
 2     <table class="form">
 3         <colgroup>
 4             <col width="100"/>
 5             <col width="auto"/>
 6         </colgroup>
 7         <tbody>
 8             <tr>
 9                 <td>用戶名:</td>
10                 <td>
11                     <input id="txtUsername" type="text" name="username" />
12                 </td>
13             </tr>
14             <tr>
15                 <td>Email:</td>
16                 <td>
17                     <input id="txtEmail" type="text" name="email" />
18                 </td>
19             </tr>
20             <tr>
21                 <td>語言:</td>
22                 <td>
23                     <select id="ddlLanguages" name="language">
24                         <option value="zh-cn">中文</option>
25                         <option value="en-us">英文</option>
26                     </select>
27                 </td>
28             </tr>
29             <tr>
30                 <td>性別:</td>
31                 <td id="genders">
32                     <input type="radio" name="gender" value="@(Taoad.Web.Publics.Controllers.Gender.Unknown)" id="rdUnknown" />
33                     <label for="rdUnknown">未知</label>
34                     <input type="radio" name="gender" value="@(Taoad.Web.Publics.Controllers.Gender.Male)" id="rdMale" />
35                     <label for="rdMale"></label>
36                     <input type="radio" name="gender" value="@(Taoad.Web.Publics.Controllers.Gender.Female)" id="rdFemale" />
37                     <label for="rdFemale"></label>
38                 </td>
39             </tr>
40             <tr>
41                 <td>角色:</td>
42                 <td id="roles">
43                     <input type="checkbox" name="roleids" value="1" id="cb1" />
44                     <label for="cb1">管理員</label>
45                     <input type="checkbox" name="roleids" value="2" id="cb2" />
46                     <label for="cb2">部門經理</label>
47                     <input type="checkbox" name="roleids" value="3" id="cb3" />
48                     <label for="cb3">客戶</label>
49                 </td>
50             </tr>
51             <tr>
52                 <td>時間:</td>
53                 <td>
54                     <ul id="jobs">
55                     </ul>
56                     <input type="button" value="添加" id="btnAddJob"/>
57                 </td>
58             </tr>
59             <tr>
60                 <td></td>
61                 <td>
62                     <input type="button" value="保存" id="btnSave"/>
63                     <input type="button" value="取消" id="btnCancel" />
64                 </td>
65             </tr>
66         </tbody>
67     </table>
68 </form>
69 <hr/>
70 <div id="json">
71 </div>

JS:

 1 <script language="javascript" type="text/javascript">
 2     $(document).ready(function () {
 3         $("#btnAddJob").click(function() {
 4             var $newLi = $(html);
 5             $("#jobs").append($newLi);
 6             bindLi($newLi);
 7         });
 8 
 9         $("#btnSave").click(function() {
10             var data = $("#formUserEditor").serialize();
11             $("#jobs li").each(function(i) {
12                 var prefix = "&jobs[" + i + "]";
13                 data += prefix + ".job=" + $(this).find(".job-id").val();
14                 data += prefix + ".from=" + $(this).find(".job-from").val();
15                 data += prefix + ".to=" + $(this).find(".job-to").val();
16             });
17             demo.ajax.post("/demo/saveuser", data, function(json) {
18                 $("#json").html(json);
19             });
20         });
21     });
22 
23     function bindLi(li) {
24         $(li).find(".btn-add").click(function () {
25             var $li = $(this).closest("li");
26             var $newLi = $(html);
27             $li.after($newLi);
28             bindLi($newLi);
29         });
30         $(li).find(".btn-delete").click(function () {
31             $(this).closest("li").remove();
32         });
33     }
34 
35     var html = ‘<li>36                     <select class="job-id">37                         <option value="job1">工作1</option>38                         <option value="job2">工作2</option>39                     </select>40                     <input type="text" placeholder="開始時間"  class="job-from"/>41                     ————42                     <input type="text" placeholder="結束時間"  class="job-to"/>43                     <a href="javascript:void(0);" class="btn-add">添加</a> |44                     <a href="javascript:void(0);" class="btn-delete">刪除</a>45                 </li>‘;
46 </script>

如果是如下的表單數據:

技術分享

點擊保存之後,返回的JSON數據為:

技術分享

可以看到所有的表單數據都保存成功了。

再看看request信息:

技術分享

請註意content-type的值。

實際上,POST到服務器的表單數據只是一個字符串,如下:

技術分享

復制出來就是下面這樣的字符串:

ajax=true&username=leo&email=leo%40gmail.com&language=zh-cn&gender=Unknown&roleids=1&roleids=3&jobs[0].job=job1&jobs[0].from=9:00&jobs[0].to=10:00&jobs[1].job=job2&jobs[1].from=10:00&jobs[1].to=11:00

  

由此可知,可用JS來拼接字符串,將整個表單通過鍵值對的形式序列化成一個字符串,再將該字符串傳到服務器,這時DefaultModelBinder就可以自動解析實體類了。

關鍵點在於,對於List或者數組類型的數據,要加上數組下標。這樣,任意復雜的數據結構,DefaultModelBinder都可以自動解析了。

MVC--DefaultModelBinder解析request參數