Say you create a form using ASP.NET MVC that has a dynamic number of form elements.
For instance, you need a checkbox for each product, and the number of products ch
Depending on the binders you are using, this should work:
<%var i = 0;
foreach (var product (IList<ProductSelection>)ViewData["products"]) {%>
<%=Html.Hidden(string.Format("products[{0}].Id", i), product.Id)%>
<%=Html.Checkbox(string.Format("products[{0}].Selected", i))%>
<%=product.Name%><br/>
<%}%>
...which will result in HTML something like this (notice the array notation on the names):
<input name="products[0].Id" type="hidden" value="123">
<input name="products[0].Selected" type="checkbox">
Widget
<input name="products[1].Id" type="hidden" value="987">
<input name="products[1].Selected" type="checkbox">
Gadget
...and the controller method that handles the post:
public ActionResult SelectProducts(IList<ProductSelection> products)
{
...
}
Upon binding, products parameter will contain two instances of ProductSelection.
One caveat is that I have not used the new default binding for complex objects. Rather I am using either the NameValueDeserializer or CastleBind, both from MvcContrib. They both behave this way. I am guessing binding in the Beta will work the same way.
Per Craig's answer.. that is safer. There are quirks to posting multiple form elements with the same name. I would add that it would be wise to wrap the logic that makes the "collection" of controls in a way similar to WebForms. Web Forms prepend the container control's name and adds an index. For example, in a Repeater the form elements inside would be named (something like) RepeaterName_Element1, RepeaterName_Element2. When you go to get the elements out, you have to use FindControl or something of the sort.
Depending on your data, you could either output a 'CheckboxList' (which is not possible in the newer versions any more) and use a string[]
parameter, or you could set up multiple forms and just modify the action.
Just give each checkbox a unique name value:
<input class="approveCheck" id="<%= "approveCheck" + recordId %>"
name="<%= "approveCheck" + recordId %>" type="checkbox" />
Then parse the list of form values in the Action, after submit:
foreach (var key in Request.Form.Keys)
{
string keyString = key.ToString();
if (keyString.StartsWith("approveCheck", StringComparison.OrdinalIgnoreCase))
{
string recNum = keyString.Substring(12, keyString.Length - 12);
string approvedKey = Request.Form["approveCheck" + recNum];
bool approved = !String.IsNullOrEmpty(approvedKey);
// ...
You don't need to pass form values as arguments; you can just get them from Request.Form.
One other option: write a model binder to change the list into a custom type for form submission.