原文地址 这是我在CodeProject上面看到的一篇文章,这里是我翻译的中文版,如果有任何翻译不恰当之处,还望各位不吝赐教!
Models
在开始之前,我想花一点时间阐述一下我们将要在C#中绑定的模型(Models)。我们来创建一个包含Friend和Address的Person模型。
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的详文:
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视图里面所需要就是下面的代码:
@using (Html.BeginForm(“Edit”, “Person”)){<div>@Html.HiddenFor(m => m.Id)>>}
所需要的HTML非常简单:
===>Name:==>>Submit>
默认的绑定器从input标签里面获得name特性的值,绑定到C#对象属性。Value属性设置初始值。下面就是当我点击“Submit”按钮的时候,,Html请求体的内容。
Id=1&Name=Jane+Doe
我希望你将HTTP请求看做一些键值对,因此,name指向C#中的name属性,value指向它的值,这和下述的Controller中的代码完成了同样的工作。
var vm = new PersonViewModel();vm.Id = 1;vm.Name = “Jane Doe”;
让人吃惊的是,默认的绑定器如何将C#中的强类型考虑进来的。String类型获得string值,integer类型获得integer值。
绑定到内嵌类型
让我们将目光放在内嵌类型上面,我们所需要的代码如下:
<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的时候会获取整个对象。
new PersonViewModel{Friend = new Person{Id = 2,Name = “Jon Doe”}};
它从下面的HTML中获取所有的信息:
==>==>
只要你将name映射到正确的对象属性上,默认的模型绑定器将会处理剩下的工作。
绑定列表
默认的绑定器需要一个跟踪对象列表的方法,按照惯例,它使用了一个类似于数组的语法来完成这个事情。Look:
for (var i = 0; i < Model.Addresses.Count(); i++){<div>@Html.HiddenFor(m => m.Addresses[i].Id)>State:>}
这是HTML部分
==>City:==>==>==>City:==>==></div>
从个人角度来说,我并不喜欢这种古怪的语法。如果你回顾ViewModel,你也许已经注意到了,我使用了Address[]数组来完成了这魔法般的工作。默认的模型绑定器需要对索引敏感。因此,只要你从0索引开始,后续索引连续递增,它才会工作,一定要确定你的索引之间没有间隔。
总结活在当下,别在怀念过去或者憧憬未来中浪费掉你现在的生活。