The DefaultModelBinder in ASP.NET MVC -ASP.NET MVC的默认模型绑定器
2015-05-22 09:43
801 查看
原文地址
这是我在CodeProject上面看到的一篇文章,这里是我翻译的中文版,如果有任何翻译不恰当之处,还望各位不吝赐教!
这种设定有点不合理,因为我希望一个Person拥有不止一个Friend。由于我来自美国,我决定在Address里面保留State。
你可以将Person和Address看做是数据库里面的数据表,我个人推荐在ViewModels里面使用Model的强类型视图。我比较喜欢将ViewModels看做是数据的汇总。
下面是Controller的详文:
你可能会奇怪,在德克萨斯州究竟有没有雅典和巴黎。
你可以开始想象默认的绑定器如何处理整个ViewModel,我写了少量的代码来处理大量的数据。
所需要的HTML非常简单:
默认的绑定器从input标签里面获得name特性的值,绑定到C#对象属性。Value属性设置初始值。下面就是当我点击“Submit”按钮的时候,Html请求体的内容。
我希望你将HTTP请求看做一些键值对,因此,name指向C#中的name属性,value指向它的值,这和下述的Controller中的代码完成了同样的工作。
让人吃惊的是,默认的绑定器如何将C#中的强类型考虑进来的。String类型获得string值,integer类型获得integer值。
这看起来非常复杂,但是,默认绑定器所看到的全部就是Friend.Name。因此,它会对所有C#对象进行递归遍历,寻找对应的属性。整个引擎自带递归功能,所以你想走多深就能走多深,这可以让复杂的数据集被轻松使用。
如果你回顾Controller,你会发现PersonViewModel vm被作为了Edit()的参数。默认的模型绑定器在绑定到ViewModel的时候会获取整个对象。
它从下面的HTML中获取所有的信息:
只要你将name映射到正确的对象属性上,默认的模型绑定器将会处理剩下的工作。
这是HTML部分
从个人角度来说,我并不喜欢这种古怪的语法。如果你回顾ViewModel,你也许已经注意到了,我使用了Address[]数组来完成了这魔法般的工作。默认的模型绑定器需要对索引敏感。因此,只要你从0索引开始,后续索引连续递增,它才会工作,一定要确定你的索引之间没有间隔。
下面是HTTP请求内容:
现在你也许可以回头看看我在Controller中穿件的C#对象,去感受一下上面这一堆文本信息。尽情感受默认模型绑定器的美丽吧,美到你哭。
如果你感兴趣的话,你可以在GitHub上下载整个样例。
这是我在CodeProject上面看到的一篇文章,这里是我翻译的中文版,如果有任何翻译不恰当之处,还望各位不吝赐教!
Models
在开始之前,我想花一点时间阐述一下我们将要在C#中绑定的模型(Models)。我们来创建一个包含Friend和Address的Person模型。[code]public class Person { public int Id { get; set; } public string Name { get; set; } } public class Address { public int Id { get; set; } public string City { get; set; } public string State { get; set; } } public class PersonViewModel { public int Id { get; set; } public string Name { get; set; } public Person Friend { get; set; } public Address[] Addresses { get; set; } }
这种设定有点不合理,因为我希望一个Person拥有不止一个Friend。由于我来自美国,我决定在Address里面保留State。
你可以将Person和Address看做是数据库里面的数据表,我个人推荐在ViewModels里面使用Model的强类型视图。我比较喜欢将ViewModels看做是数据的汇总。
下面是Controller的详文:
[code]public class PersonController : Controller { public ActionResult Edit() { var vm = new PersonViewModel { Id = 1, Name = "Jane Doe", Friend = new Person { Id = 2, Name = "Jon Doe" }, Addresses = new Address[] { new Address { Id = 1, City = "Athens", State = "Texas" }, new Address { Id = 2, City = "Paris", State = "Texas" } } }; return View(vm); } [HttpPost] public ActionResult Edit(PersonViewModel vm) { return View("Details", vm); } }
你可能会奇怪,在德克萨斯州究竟有没有雅典和巴黎。
你可以开始想象默认的绑定器如何处理整个ViewModel,我写了少量的代码来处理大量的数据。
绑定到复杂数据类型
你可以把模型绑定器看做一个将HTTP文本信息转换成C#对象的机器,为了绑定复杂C#类型,我们在Razor视图里面所需要就是下面的代码:[code]@using (Html.BeginForm("Edit", "Person")) { <div> @Html.HiddenFor(m => m.Id) <label>Name:</label> <span>@Html.TextBoxFor(m => m.Name)</span> </div> <div> <button>Submit</button> </div> }
所需要的HTML非常简单:
[code]<form action="/" method="post"> <div> <input id="Id" name="Id" type="hidden" value="1" /> <label>Name:</label> <span> <input id="Name" name="Name" type="text" value="Jane Doe" /> </span> </div> <div> <button>Submit</button> </div> </form>
默认的绑定器从input标签里面获得name特性的值,绑定到C#对象属性。Value属性设置初始值。下面就是当我点击“Submit”按钮的时候,Html请求体的内容。
[code]Id=1&Name=Jane+Doe
我希望你将HTTP请求看做一些键值对,因此,name指向C#中的name属性,value指向它的值,这和下述的Controller中的代码完成了同样的工作。
[code]var vm = new PersonViewModel(); vm.Id = 1; vm.Name = "Jane Doe";
让人吃惊的是,默认的绑定器如何将C#中的强类型考虑进来的。String类型获得string值,integer类型获得integer值。
绑定到内嵌类型
让我们将目光放在内嵌类型上面,我们所需要的代码如下:[code]<div> <label>Friend:</label> @Html.HiddenFor(m => m.Friend.Id) <span>@Html.TextBoxFor(m => m.Friend.Name)</span> </div>
这看起来非常复杂,但是,默认绑定器所看到的全部就是Friend.Name。因此,它会对所有C#对象进行递归遍历,寻找对应的属性。整个引擎自带递归功能,所以你想走多深就能走多深,这可以让复杂的数据集被轻松使用。
如果你回顾Controller,你会发现PersonViewModel vm被作为了Edit()的参数。默认的模型绑定器在绑定到ViewModel的时候会获取整个对象。
[code]new PersonViewModel { Friend = new Person { Id = 2, Name = "Jon Doe" } };
它从下面的HTML中获取所有的信息:
[code]<div> <label>Friend:</label> <input id="Friend_Id" name="Friend.Id" type="hidden" value="2" /> <span> <input id="Friend_Name" name="Friend.Name" type="text" value="Jon Doe" /> </span> </div>
只要你将name映射到正确的对象属性上,默认的模型绑定器将会处理剩下的工作。
绑定列表
默认的绑定器需要一个跟踪对象列表的方法,按照惯例,它使用了一个类似于数组的语法来完成这个事情。Look:[code]for (var i = 0; i < Model.Addresses.Count(); i++) { <div> @Html.HiddenFor(m => m.Addresses[i].Id) <label>City:</label> <span>@Html.TextBoxFor(m => m.Addresses[i].City)</span> <label>State:</label> <span>@Html.TextBoxFor(m => m.Addresses[i].State)</span> </div> }
这是HTML部分
[code]<div> <input id="Addresses_0__Id" name="Addresses[0].Id" type="hidden" value="1" /> <label>City:</label> <span> <input id="Addresses_0__City" name="Addresses[0].City" type="text" value="Athens" /> </span> <label>State:</label> <span> <input id="Addresses_0__State" name="Addresses[0].State" type="text" value="Texas" /> </span> </div> <div> <input id="Addresses_1__Id" name="Addresses[1].Id" type="hidden" value="2" /> <label>City:</label> <span> <input id="Addresses_1__City" name="Addresses[1].City" type="text" value="Paris" /> </span> <label>State:</label> <span> <input id="Addresses_1__State" name="Addresses[1].State" type="text" value="Texas" /> </span> </div>
从个人角度来说,我并不喜欢这种古怪的语法。如果你回顾ViewModel,你也许已经注意到了,我使用了Address[]数组来完成了这魔法般的工作。默认的模型绑定器需要对索引敏感。因此,只要你从0索引开始,后续索引连续递增,它才会工作,一定要确定你的索引之间没有间隔。
总结
现在到终场演出的时候了!让我们来看看默认模型绑定器如何工作。下面是HTTP请求内容:
[code]Id=1&Name=Jane+Doe&Friend.Id=2&Friend.Name=Jon+Doe&Addresses%5B0%5D.Id=1& Addresses%5B0%5D.City=Athens&Addresses%5B0%5D.State=Texas& Addresses%5B1%5D.Id=2&Addresses%5B1%5D.City=Paris&Addresses%5B1%5D.State=Texas
现在你也许可以回头看看我在Controller中穿件的C#对象,去感受一下上面这一堆文本信息。尽情感受默认模型绑定器的美丽吧,美到你哭。
如果你感兴趣的话,你可以在GitHub上下载整个样例。
相关文章推荐
- asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证
- ASP.NET MVC中默认Model Binder绑定Action参数为List、Dictionary等集合的实例
- asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证
- asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证
- asp.net mvc源码分析-DefaultModelBinder 集合绑定
- asp.net mvc源码分析-DefaultModelBinder 集合绑定
- 如何应用Asp.Net Mvc内建功能(DefaultModelBinder)实现简单类型、复杂类型、集合类型,以及字典类型的自动绑定
- asp.net mvc源码分析-Action篇 DefaultModelBinder
- (转)How to use the ASP.NET MVC ModelBinder
- 你从未知道如此强大的ASP.NET MVC DefaultModelBinder
- Asp.net MVC的Model Binder工作流程以及扩展方法(3) - DefaultModelBinder
- 一起谈.NET技术,ASP.NET MVC & EF 构建智能查询 二、模型的设计与ModelBinder
- 深入分析 ASP.NET Mvc 1.0 – 4. 使用ModelBinder绑定Action的参数
- ASP.NET MVC Model Binding(模型绑定)
- ModelBinder——ASP.NET MVC Model绑定的核心
- ModelBinder——ASP.NET MVC Model绑定的核心
- 设置页面的默认焦点控件和默认接受事件控件How Do I Set the DefaultFocus or DefaultButton in a Page Based on a Master Page in ASP.NET 2.0
- MVC重写DefaultModelBinder实现自定义模型绑定
- Asp.net MVC DefaultModelBinder分析
- ASP.NET MVC & EF 构建智能查询 二、模型的设计与ModelBinder