Here is some code that provides a helper to rebind arrays of complex types. Any class T which has a parameterless constructor can be enumerated on the page as
name="Person[-1].Id"
name="Person[-1].Name"
name="Person[0].Id"
name="Person[0].Name"
name="Person[1].Id"
name="Person[1].Name"
and then rebound by calling ModelBinderHelper.GetEnumerable<Person>(bindingContext)
Note that this depends on the IModelBinder interface from Asp.Net Mvc Beta. We were using MvcContrib's NameValueDeserializer before the advent of IModelBinder
1 /// <summary>
2 /// Helper class for model binding
3 /// </summary>
4 public class ModelBinderHelper
5 {
6 /// <summary>
7 /// Get an array of a complex type, T, from the form.
8 /// Convention on form is TypeName[-1], TypeName[0], TypeName[1], etc.
9 /// The type must have a parameterless public constructor.
10 /// </summary>
11 public static IEnumerable GetEnumerable(ModelBindingContext parentBindingContext)
12 where T : class, new()
13 {
14 string typeName = typeof(T).Name;
15 var prefixRegex = new Regex(string.Format(@"^{0}\[(-?\d+)\]", typeName));
16
17 return parentBindingContext.HttpContext.Request.Form.AllKeys
18 .Select(s => prefixRegex.Match(HttpUtility.UrlDecode(s)))
19 .Where(m => m != Match.Empty)
20 .Select(m => long.Parse(m.Groups[1].Value))
21 .Distinct()
22 .Select(
23 index => ModelBinders.GetBinder(typeof (T)).BindModel(GetContext(index, parentBindingContext)).Value as T);
24 }
25
26 private static ModelBindingContext GetContext(long index, ModelBindingContext bindingContext) where T : class, new()
27 {
28 string typeName = typeof(T).Name;
29 return new ModelBindingContext(bindingContext.Controller.ControllerContext,
30 bindingContext.ValueProvider,
31 typeof (T),
32 string.Format("{0}[{1}]", typeName, index),
33 () => new T(),
34 bindingContext.ModelState,
35 (property) => true);
36 }
37 }