Depending on the binders you use, 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 cause HTML to be something like this (note the array notation for 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 processes the message:
public ActionResult SelectProducts(IList<ProductSelection> products) { ... }
When bound, the products parameter will contain two instances of ProductSelection.
One caveat is that I did not use the new default binding for complex objects. Rather, I use either NameValueDeserializer or CastleBind, as from MvcContrib. They both behave like that. I assume beta binding will work the same.
source share