Model Binding To A List
[文章来源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的更多相关文章
- [ASP.NET MVC 小牛之路]15 - Model Binding
Model Binding(模型绑定)是 MVC 框架根据 HTTP 请求数据创建 .NET 对象的一个过程.我们之前所有示例中传递给 Action 方法参数的对象都是在 Model Binding ...
- Asp.net MVC使用Model Binding解除Session, Cookie等依赖
上篇文章"Asp.net MVC使用Filter解除Session, Cookie等依赖"介绍了如何使用Filter来解除对于Session, Cookie的依赖.其实这个也可以通 ...
- [ASP.NET MVC] Model Binding With NameValueCollectionValueProvider
[ASP.NET MVC] Model Binding With NameValueCollectionValueProvider 范例下载 范例程序代码:点此下载 问题情景 一般Web网站,都是以H ...
- 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 ...
- 【ASP.NET MVC 学习笔记】- 16 Model Binding(模型绑定)
本文参考:http://www.cnblogs.com/willick/p/3424188.html. 1.Model Binding是Http请求和Action方法之间的桥梁,是MVC框架根据Htt ...
- .NET Core开发日志——Model Binding
ASP.NET Core MVC中所提供的Model Binding功能简单但实用,其主要目的是将请求中包含的数据映射到action的方法参数中.这样就避免了开发者像在Web Forms时代那样需要从 ...
- 运用模型绑定和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 ...
- [置顶] ASP.NET MVC - Model Binding
Http Request 到Input Model的绑定按照model的类型可分为四种情况. Primitive type Collection of primitive type Complex t ...
- MVC3 Model Binding验证方式
1.使用ModelState在Action中进行验证 [HttpPost] public ViewResult MakeBooking(Appointment appt) { if (string.I ...
随机推荐
- GCD(1222)Wolf and Rabbit
Problem Description There is a hill with n holes around. The holes are signed from 0 to n-1. A rabbi ...
- jquery 元素控制(附加元素/其他内容)引进和应用
一个.在内部元素/外部附加元件 append,prepend:加入到该子元素 before,after:元素加入 html: <div id="content"> 在 ...
- python_基础学习_04_mysql库验证与安装(mysql-python,mysql.connector)
验证python-mysql是否安装 1:python 2: import MySQLdb 安装步骤: 1.sudo apt-get install python-setuptools 2.sudo ...
- CSharp设计模式读书笔记(8):桥接模式(学习难度:★★★☆☆,使用频率:★★★☆☆)
桥接模式(Bridge Pattern): 将抽象部分与它的实现部分分离,使它们都可以独立地变化.它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模 ...
- JavaScript 奇技淫巧
JavaScript 奇技淫巧 这里记录一下以前学习各种书籍和文章里边出现的JS的小技巧,分享给大家,也供自己查阅,同时感谢那些发现创造和分享这些技巧的前辈和大牛们. 1.遍历一个obj的属性到数组 ...
- easyui datagrid load 封装 参数问题 js 作用域
var temp = { LoginAccount: $('#LoginAccount').val(), ShopName: $('#ShopName').val() }; function doSe ...
- 使用Jenkins来构建Docker容器
使用Jenkins来构建Docker容器(Ubuntu 14.04) 当开发更新了代码,提交到Gitlab上,然后由测试人员触发Jenkins,于是一个应用的新版本就被构建了.听起来貌似很简单,dua ...
- ftk学习记录(IME文章)
[声明:版权全部,欢迎转载.请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 前面说的是全屏设置,还是请大家看一下效果图. watermark/2/text/aHR0cDovL ...
- 文档PDF开放
108个大数据文档PDF开放下载 投递人 itwriter 发布于 2015-01-29 13:34 评论(13) 有2251人阅读 原文链接 [收藏] « » 文/36 大数据 总有人问我 ...
- Oracle / PLSQL写语句的时候常使用的函数
最近在学习数据库方面的知识,做个标记. 这里有英文解释,建议多看看英文文档: https://www.techonthenet.com/oracle/functions/ 下面开始记录一下,自己在Or ...