MVC--DefaultModelBinder解析request参数

转载: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都可以自动解析了。

时间: 2024-10-25 15:33:11

MVC--DefaultModelBinder解析request参数的相关文章

简析Spring MVC 数据解析

简析Spring MVC 数据解析 特别说明:本文使用spring 版本为 4.1.3 常用数据提交方式: 1. form 表单提交数据 1.1 解析form表单数据(无图片等数据) 前端代码事例: <form action="test/entity" method="post"> 用户ID:<input type="text" name="userid"/><br> 用户名:<inp

软键盘实例 request参数修改

软键盘实例 request参数修改 这里的键盘 里面的内容是乱序的,每次请求都会不一样的顺序. 键盘内容是一个DIV的背景图,方框是DIV边框.控制按钮直接在前台控制就行. 请求流程如下 JSP请求软键盘图片->action 绘制图片并记录 每个值对应的位置 JSP登录(密码位置)-->Filter把密码转换成真实密码值->登录校验Filter 代码如下 <%@ page isELIgnored="false" %> <%@ page languag

基于Java Bean Validation对Request参数进行校验的设计思路

摘自Hibernate Validator文档: 数据校验是任何一个应用程序都会用到的功能,无论是显示层还是持久层. 通常,相同的校验逻辑会分散在各个层中, 这样,不仅浪费了时间还会导致重复代码的发生. 为了避免重复, 开发人员经常会把这些校验逻辑直接写在领域模型里面, 但是这样又把领域模型代码和校验代码混杂在了一起, 而这些校验逻辑更应该是描述领域模型的元数据. JSR 303 - Bean Validation (version 1.1)- 为实体验证定义了元数据模型和API. 默认的元数据

Python学习之Argparse 解析脚本参数详解

Argparse 是 Python 标准库中推荐的命令行解析模块,经常需要解析脚本参数的话这是个方便的工具模块,摆脱万年手动 system.argv .本文和大家分享的就是python中Argparse解析脚本参数相关内容,一起来看看吧,希望对大家学习python有所帮助. 引入 import argparse parser = argparse.ArgumentParser(description='描述说明,可用于 Help 输出说明', add_help=True) parser.pars

.net mvc RazorEngine 字符串razor参数替换

在.net中有一个比较好的字符串参数替换的方案RazorEngine推荐大家看看原网站,然后做个小联系然后你就懂啦 首先呢得下载一个吧, vs中tools-> Library Paging Manager->Manager Nuget 在然后呢Install-Package RazorEngine 等待搜索结束吧,然后下载下来两个dll RazorEngine.dll  没说的一定要引用到工程里面的 System.Web.Razor.dll 这个dll工程里面是引用了的  多以会提示替换,别犹

spring mvc 编写处理带参数的Controller

在上一随笔记录的基础上,现记录编写处理带有参数的Controller. @Controller //这个注解会告知<context:component:scan> 将HomeController自动检测为一个Bean@RequestMapping("/home")  //这是根Urlpublic class HomeController {        private UserService userService;        @Autowired    public

Scala正则和抽取器:解析方法参数

在<正则表达式基础知识>中概括了正则表达式的基础知识, 本文讲解如何使用正则表达式解析方法参数,从而可以根据 DAO 自动生成 Service. 在做 Java 项目时,常常要根据 DAO 生成 Service , 而 Service 有时是简单的调用 DAO 方法.比如根据 public CreativeDO findByCreativeId(Long creativeId)  生成如下代码: public CreativeDO findByCreativeId(Long creativeI

正则表达式解析url参数

解析url参数正则:(?<=\?|&)[\w\={},:''""]*(?<=[^#]) 正好项目中要用到 捣鼓了好久还是不会.最终放弃使用split分割的方式解析发现好落伍 public static NameValueCollection QueryString(string path) { if (string.IsNullOrEmpty(path)) { return null; } var arr=path.Split(new char[] { '?' },

jQuery 解析 url 参数

应用场景: 三毛:我现在拿到一个 url 地址(https://www.google.com/search?dcr=0&ei=5C&q=param),我现在要获取 location.search 后的参数,并组成一个对象,{dcr: '0', ej: '5C', q: 'param'},怎么处理? 五毛:呃,稍等,我去谷歌一下 谷歌结果: // 解析 url 参数 (function($) { var re = /([^&=]+)=?([^&]*)/g, decodeRE