在做Asp.Net MVC项目中,都知道View负责页面展示数据或者提供页面收集数据,而所展示的数据或者收集的数据都是从Controller的Action中获取或提交到Controller的Action。
这里的数据,可能是基础类型,或者是Model,或者是Model的部分内容,或者是集合比如List或Dictionary。
数据从View传递到Controller的Action时,有几种方式,RouteData(url中的路由数据),QueryString(http get的查询参数如?page=2),Forms(表单post的数据), 或者ajax交互的json数据。
而在Controller的action中,常常希望获得这些View传递的数据,并且最好能绑定到Action希望的类型,这些类型可能是Action的基础类型参数,或者需要更新的Model,或者只更新Model的部分内容,或者是一些集合的结构如List或Dictionary。
古董方法:
[AcceptVerbs(HttpVerbs.Post)]
publicActionResultCreate()
{
Reciperecipe = newRecipe();
recipe.Name = Request.Form["Name"];
// ...
returnView();
}
前进一步:
publicActionResultCreate(FormCollection values)
{
Reciperecipe = newRecipe();
recipe.Name = values["Name"];
// ...
returnView();
}
Asp.Net Mvc: Model Binding to Simple Types, Complex Types, Collections, Dictionaries, Etc
转:http://www.cnblogs.com/tristanguo/archive/2009/02/18/1393237.html
环境:
Windows 2008, VS 2008 SP1, Asp.Net Mvc 1.0
------------------------------------------------------------------------------
本文主要实验如何应用Asp.Net Mvc内建功能(DefaultModelBinder)实现简单类型、复杂类型、集合类型,以及字典类型的自动绑定。
1. 简单类型
这里,我们将下面这个Book类称为简单类型:
public class Book { public int BookId { get; set; } public string BookName { get; set; } public string Author { get; set; } public DateTime PublishedDate { get; set; } }
假设现在需要实现添加Book的功能,那么在BookController中,会定义如下的Action:
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Create(Book book) { //TO DO //Insert book into Database return RedirectToAction("Index"); }
现在的问题便是,在View中如何命名TextBox来达到自动绑定,如下:
<div> <%using (Html.BeginForm("Create", "Book")) { %> <div> Book Name: <%=Html.TextBox("BookName")%> </div> <div> Author: <%=Html.TextBox("Author")%> </div> <div> Published Date: <%=Html.TextBox("PublishedDate")%> </div> <div> <input type="submit" id="submit" name="submit" value="submit" /> </div> <%} %> </div>
注意TextBox的name必须是对应绑定类型的PropertyName(不区分大小写)。 这样,页面表单submit后,我们便可以在BookController的“Create” Action中得到自动绑定的book对象。这里,Asp.Net Mvc还支持在TextBox的name中加上变量名称前缀的情形:
<div> <%using (Html.BeginForm("Create", "Book")) { %> <div> Book Name: <%=Html.TextBox("book.BookName")%> </div> <div> Author: <%=Html.TextBox("book.Author")%> </div> <div> Published Date: <%=Html.TextBox("book.PublishedDate")%> </div> <div> <input type="submit" id="submit" name="submit" value="submit" /> </div> <%} %> </div>
需要注意的是: 1)前缀"book"必须与Action中接收的Book参数名一致 2)如果加了前缀,那么所有的都要加
2. 复杂类型
现在对Book类作些许改动,并引入Author类:
public class Book { public int BookId { get; set; } public string BookName { get; set; } public Author Author { get; set; } public DateTime PublishedDate { get; set; } } public class Author { public int AuthorId { get; set; } public string AuthorName { get; set; } public string Nation { get; set; } }
这里,将改动后的Book类称为复杂类。这时,Book类多了一个对Author类的引用。现在,保持BookController中的"Create" Action不变,来看View中的TextBox改如何命名以实现Book类型的自动绑定:
<div> <%using (Html.BeginForm("Create", "Book")) { %> <div> Book Name: <%=Html.TextBox("BookName")%> </div> <div> Published Date: <%=Html.TextBox("PublishedDate")%> </div> <div> Author's Name: <%=Html.TextBox("Author.AuthorName")%> </div> <div> Author's Nation: <%=Html.TextBox("Author.Nation")%> </div> <div> <input type="submit" id="submit" name="submit" value="submit" /> </div> <%} %> </div>
OK,测试通过,想必你也知道命名规则了,要绑定Book类型中的Author类型,必须加上"Author."的前缀。 如果你喜欢,你还可以在所有TextBox名称前面再加"book."的前缀。
3. 集合类型
为避免问题复杂化,我们用回原来的简单Book类型:
public class Book { public int BookId { get; set; } public string BookName { get; set; } public string Author { get; set; } public DateTime PublishedDate { get; set; } }
现在,把BookController的"Create" Action改为接收IList<Book>的参数:
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Create(IList<Book> books) { //TO DO //Insert book into Database return RedirectToAction("Index"); }
然后,在View中运用以下命名规则,以自动绑定IList<book>类型
<div> <%using (Html.BeginForm("Create", "Book")) { %> <div> Book Name: <%=Html.TextBox("books[0].BookName")%> </div> <div> Published Date: <%=Html.TextBox("books[0].PublishedDate")%> </div> <div> Author's Name: <%=Html.TextBox("books[0].Author")%> </div> <div> Book Name: <%=Html.TextBox("books[1].BookName")%> </div> <div> Published Date: <%=Html.TextBox("books[1].PublishedDate")%> </div> <div> Author's Name: <%=Html.TextBox("books[1].Author")%> </div> <div> <input type="submit" id="submit" name="submit" value="submit" /> </div> <%} %> </div>
可以看到如下规则:Action的变量名"books"加上中括号和索引作为前缀,索引必须从0开始,并且必须连续。 通过此命名规则,可以绑定任意集合类型:IList<Book>, ICollection<Book>, IEnumerable<Book>, List<Book>, Book[]等。
4. 字典类型
仍以简单Book类型为例,现在将"Create" Action改为接收IDictionary<Book>类型
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Create(IDictionary<string, Book> books) { //TO DO //Insert book into Database return RedirectToAction("Index"); }
相应的,View中的命名如下:

<div> <%using (Html.BeginForm("Create", "Book")) { %> <div> Book SN: <%=Html.TextBox("books[0].Key") %> </div> <div> Book Name: <%=Html.TextBox("books[0].Value.BookName")%> </div> <div> Published Date: <%=Html.TextBox("books[0].Value.PublishedDate")%> </div> <div> Author's Name: <%=Html.TextBox("books[0].Value.Author")%> </div> <div> Book SN: <%=Html.TextBox("books[1].Key") %> </div> <div> Book Name: <%=Html.TextBox("books[1].Value.BookName")%> </div> <div> Published Date: <%=Html.TextBox("books[1].Value.PublishedDate")%> </div> <div> Author's Name: <%=Html.TextBox("books[1].Value.Author")%> </div> <div> <input type="submit" id="submit" name="submit" value="submit" /> </div> <%} %> </div>
可以看出,对于IDictioinary<Book>类型,在命名规则上,相比于集合类型,多了"Key"和"Value”的字眼。另,此规则也适用于Action参数类型为Dictionary<Book>的情形。
总结:
由此看来,只要我们遵循一定的命名规则,就可以轻松实现各种类型的自动绑定了。 当然,Asp.Net Mvc还支持自定义ModelBinder扩展