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 ...
随机推荐
- 使用 CXF 做 webservice 简单例子[转]
Apache CXF 是一个开放源代码框架,提供了用于方便地构建和开发 Web 服务的可靠基础架构.它允许创建高性能和可扩展的服务,您可以将这样的服务部署在 Tomcat 和基于 Spring 的轻量 ...
- [VirtualBox] - Install Oracle Linux 7 on Oracle VirtualBox
I'll start coding with JEE soon. Product environment adopts Oracle + WebLogic in Linux, technology a ...
- Bootstrap-maxlength使用
这是一个很酷jQuery实现Bootstrap小工具,输入用户同意的字符数.它可以让你显示字符用户插入的最大长度. 1.引入jquery.js及bootstrap-maxlength.js 2.给页面 ...
- The Swift Programming Language-官方教程精译Swift(4)字符串和字符
String 是一个有序的字符集合,例如 "hello, world", "albatross".Swift 字符串通过 String 类型来表示,也可以表示为 ...
- javascritpt 原型链
// 基类 var BaseCalculator = function(){ this.decimalDigits = 2; }; // public BaseCalculator.prototype ...
- 如何使用Visual Studio 2013 开发PHP5.6项目
原文如何使用Visual Studio开发PHP项目 在windows下开发php除了记事本 DW 以及一帮Zend studio,Eclipse,NetBeans之流以外,个人感觉还是vsiual ...
- android KK版本号,如何更改蓝牙设备类型
mediatek/external/bluetooth/bt_cust/bt_cust_table.h { .name = "ClassOfDevice", ...
- Github资源汇集
Github资源汇集 突然发现申请博客园已经两年有余,没有发表过一篇文章,十分惭愧.言归正传,先分享一下两年来收集的部分编程资源,大部分为Github上的项目.虽然网上这样的分享已不在少数,但不如我理 ...
- .NET开源项目 TOP 25
.NET开源项目 TOP 25 如果知道.NET项目在开源中国的git上所占的比重只有5%的话,为什么这个<2014年国人开发的最热门的开源软件TOP 100>榜中.NET项目那么少就是情 ...
- selenium之多线程启动grid分布式测试框架封装(三)
七.工具类,线程监控器类创建 utils包中,创建java类:RemoteThreadStatusMonitor.java package com.lingfeng.utils; /** * 此监控器 ...