[文章来源see here]

Using the DefaultModelBinder in ASP.NET MVC, you can bind submitted form values to arguments of an action method. But what if that argument is a collection? Can you bind a posted form to an ICollection<T>?

Sure thing! It’s really easy if you’re posting a bunch of primitive types. For example, suppose you have the following action method.

public ActionResult UpdateInts(ICollection<int> ints) {

  return View(ints);
}

You can bind to that by simply submitting a bunch of form fields each having the same name. For example, here’s an example of a form that would bind to this, assuming you keep each value a proper integer.

<form method="post" action="/Home/UpdateInts">
<input type="text" name="ints" value="1" />
<input type="text" name="ints" value="4" />
<input type="text" name="ints" value="2" />
<input type="text" name="ints" value="8" />
<input type="submit" />
</form>

If you were to take fiddler and look at what data actually gets posted when clicking the submit button, you’d see the following.

ints=1&ints=4&ints=2&ints=8

The default model binder sees all these name/value pairs with the same name and converts that to a collection with the key ints, which is then matched up with the ints parameter to your action method. Pretty simple!

Where it gets trickier is when you want to post a list of complex types. Suppose you have the following class and action method.

public class Book {
public string Title { get; set; }
public string Author { get; set; }
public DateTime DatePublished { get; set; }
} //Action method on HomeController
public ActionResult UpdateProducts(ICollection<Book> books) {
return View(books);
}

You might think we could simply post the following to that action method:

Title=title+one&Author=author+one&DateTime=1/23/1975 &Title=author+two&Author=author+two&DateTime=6/6/2007…

Notice how we simply repeat each property of the book in the form post data? Unfortunately, that wouldn’t be a very robust approach. One reason is that we can’t distinguish from the fact that there may well be another Title input unrelated to our list of books which could throw off our binding.

Another reason is that the checkbox input does not submit a value if it isn’t checked. Most input fields, when left blank, will submit the field name with a blank value. With a checkbox, neither the name nor value is submitted if it’s unchecked! This again can throw off the ability of the model binder to match up submitted form values to the correct object in the list.

To bind complex objects, we need to provide an index for each item, rather than relying on the order of items. This ensures we can unambiguously match up the submitted properties with the correct object.

Here’s an example of a form that submits three books.

<form method="post" action="/Home/Create">

    <input type="text" name="[0].Title" value="Curious George" />
<input type="text" name="[0].Author" value="H.A. Rey" />
<input type="text" name="[0].DatePublished" value="2/23/1973" /> <input type="text" name="[1].Title" value="Code Complete" />
<input type="text" name="[1].Author" value="Steve McConnell" />
<input type="text" name="[1].DatePublished" value="6/9/2004" /> <input type="text" name="[2].Title" value="The Two Towers" />
<input type="text" name="[2].Author" value="JRR Tolkien" />
<input type="text" name="[2].DatePublished" value="6/1/2005" /> <input type="submit" />
</form>

Note that the index must be an unbroken sequence of integers starting at 0 and increasing by 1 for each element.

The new expression based helpers in ASP.NET MVC 2 will produce the correct format within a for loop. Here’s an example of a view that outputs this format:

<%@ Page Inherits="ViewPage<IList<Book>>" %>

<% for (int i = 0; i < 3; i++) { %>

  <%: Html.TextBoxFor(m => m[i].Title) %>
<%: Html.TextBoxFor(m => m[i].Author) %>
<%: Html.TextBoxFor(m => m[i].DatePublished) %> <% } %>

It also works with our templated helpers. For example, we can take the part inside the for loop and put it in a Books.ascx editor template.

<%@ Control Inherits="ViewUserControl<Book>" %>

<%: Html.TextBoxFor(m => m.Title) %>
<%: Html.TextBoxFor(m => m.Author) %>
<%: Html.TextBoxFor(m => m.DatePublished) %>

Just add a folder named EditorTemplates within the Views/Shared folder and add Books.ascx to this folder.

Now change the original view to look like:

<%@ Page Inherits="ViewPage<IList<Book>>" %>

<% for (int i = 0; i < 3; i++) { %>

  <%: Html.EditorFor(m => m[i]) %>

<% } %>
Non-Sequential Indices

Well that’s all great and all, but what happens when you can’t guarantee that the submitted values will maintain a sequential index? For example, suppose you want to allow deleting rows before submitting a list of books via JavaScript.

The good news is that by introducing an extra hidden input, you can allow for arbitrary indices. In the example below, we provide a hidden input with the.Index suffix for each item we need to bind to the list. The name of each of these hidden inputs are the same, so as described earlier, this will give the model binder a nice collection of indices to look for when binding to the list.

<form method="post" action="/Home/Create">

    <input type="hidden" name="products.Index" value="cold" />
<input type="text" name="products[cold].Name" value="Beer" />
<input type="text" name="products[cold].Price" value="7.32" /> <input type="hidden" name="products.Index" value="123" />
<input type="text" name="products[123].Name" value="Chips" />
<input type="text" name="products[123].Price" value="2.23" /> <input type="hidden" name="products.Index" value="caliente" />
<input type="text" name="products[caliente].Name" value="Salsa" />
<input type="text" name="products[caliente].Price" value="1.23" /> <input type="submit" />
</form>

Unfortunately, we don’t have a helper for generating these hidden inputs. However, I’ve hacked together an extension method which can render this out for you.

When you’re creating a form to bind a list, add the following hidden input and it will add the appropriate hidden input to allow for a broken sequence of indices. Use at your own risk!I’ve only tested this in a couple of scenarios. I’ve included a sample project with multiple samples of binding to a list which includes the source code for this helper.

<%: Html.HiddenIndexerInputForModel() %>

This is something we may consider adding to a future version of ASP.NET MVC. In the meanwhile, give it a whirl and let us know how it works out for you.

Model Binding To A List的更多相关文章

  1. [ASP.NET MVC 小牛之路]15 - Model Binding

    Model Binding(模型绑定)是 MVC 框架根据 HTTP 请求数据创建 .NET 对象的一个过程.我们之前所有示例中传递给 Action 方法参数的对象都是在 Model Binding ...

  2. Asp.net MVC使用Model Binding解除Session, Cookie等依赖

    上篇文章"Asp.net MVC使用Filter解除Session, Cookie等依赖"介绍了如何使用Filter来解除对于Session, Cookie的依赖.其实这个也可以通 ...

  3. [ASP.NET MVC] Model Binding With NameValueCollectionValueProvider

    [ASP.NET MVC] Model Binding With NameValueCollectionValueProvider 范例下载 范例程序代码:点此下载 问题情景 一般Web网站,都是以H ...

  4. ASP.NET MVC3 Dynamically added form fields model binding

    Adding  new Item to a list of items, inline is a very nice feature you can provide to your user. Thi ...

  5. 【ASP.NET MVC 学习笔记】- 16 Model Binding(模型绑定)

    本文参考:http://www.cnblogs.com/willick/p/3424188.html. 1.Model Binding是Http请求和Action方法之间的桥梁,是MVC框架根据Htt ...

  6. .NET Core开发日志——Model Binding

    ASP.NET Core MVC中所提供的Model Binding功能简单但实用,其主要目的是将请求中包含的数据映射到action的方法参数中.这样就避免了开发者像在Web Forms时代那样需要从 ...

  7. 运用模型绑定和web窗体显示和检索数据(Retrieving and displaying data with model binding and web forms)

    原文 http://www.asp.net/web-forms/overview/presenting-and-managing-data/model-binding/retrieving-data ...

  8. [置顶] ASP.NET MVC - Model Binding

    Http Request 到Input Model的绑定按照model的类型可分为四种情况. Primitive type Collection of primitive type Complex t ...

  9. MVC3 Model Binding验证方式

    1.使用ModelState在Action中进行验证 [HttpPost] public ViewResult MakeBooking(Appointment appt) { if (string.I ...

随机推荐

  1. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(5)-前台JqueryEasyUI前台实现

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(5)-前台JqueryEasyUI前台实现 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框 ...

  2. C# 一个WCF简单实例

    以订票为例简单应用wcf 新建一个wcf服务应用程序 在IService1.cs定义服务契约 复制代码 代码如下: namespace WcfDemo { // 注意: 如果更改此处的接口名称 &qu ...

  3. 左右linuxserver自己主动重启过程监控和简单的解决方案

    转载请注明出处:帘卷西风的专栏(http://blog.csdn.net/ljxfblog) 本周開始,新手游进行删档封測阶段,前两天表现还好,今天更新后出现几次宕机行为.比較影响玩家的測试和体验,我 ...

  4. 内置在虚拟机上64位操作系统:该主机支持 Intel VT-x,但 Intel VT-x 残

    VT-Virtual Technology. 在这里特别说一下:虚拟64位操作系统,须要特别在BIOS中打开VT支持.怎样提示:此主机不支持Intel VT-x,则不可能虚拟出64位系统. 当提示:此 ...

  5. CSS3+HTML5特效2 - 翻转效果

    先看效果,鼠标移上去看看. back front 1. 本实例需要以下元素 a. 容器BOX b. 默认显示元素FRONT c. 翻转显示元素BACK 2. 容器BOX的Height为200px,Wi ...

  6. Google Guice结合模式

    于Guice于,喷油器装配工作是一个对象图,当请求类型实例,喷油器根据推断对象如何映射到创建的实例.解决依赖.要确定如何解决的依赖就需要配置喷油器结合的方式. 要创建绑定(Binding)对象,能够继 ...

  7. [Unity3D]Unity3D游戏开发之刀光剑影特效的实现

    大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei. 我实在不明确有的人为什么不喜欢武侠/仙侠类游戏,也许是因为武侠/仙侠类游戏身上被永远烙上的国 ...

  8. JAVA学习第三十四课 (经常使用对象API)—List集合及其子类特点

    整个集合框架中最经常使用的就是List(列表)和Set(集) 一.List集合 && Set的特点 Collection的子接口: 1.List:有序(存入和取出的顺序一致),元素都有 ...

  9. phpstorm安装laravel-ide-helper实现自动完成、代码提示和跟踪

    本文讲述laravel-ide-helper的安装方法.phpstorm安装了laravel-ide-helper后可以实现代码提示.跟踪和自动补全,减少查看API文档的次数,提高开发效率. lara ...

  10. POJ 1947 树DP获得冠军

    特定N点,N-1的关系.建立了一棵树,问至少减去几个边缘节点可以被作为得到P树.树典型DP称号 dp[cur][j] :记录cur节点,为了得到一个j除去该子树的节点的边的最小数目 对当前树的每个子树 ...