ASP.NET MVC Model Binding to a List
Microsoft’s implementation of MVC is very nice; especially the Model Binding feature. What happens if you have a List<T> of objects that are part of your model? Can you still use the awesomeness that is Model Binding?
The Setup
For this example we need some models, a view model, and an editor template. I based my test around cars and their owners. Nothing too complex, but just enough to work with what I wanted to do. Each model and view model is its own class file.
Models
public class VehicleMake { public int Id { get; set; } public string Name { get; set; } } public class VehicleModel { public int Id { get; set; } public string Name { get; set; } public int VehicleMakeId { get; set; } public virtual VehicleMake Make { get; set; } } public class Vehicle { public int Id { get; set; } public int Year { get; set; } public string Color { get; set; } public int VehicleModelId { get; set; } public virtual VehicleModel Model { get; set; } } public class Owner { public int Id { get; set; } public string Name { get; set; } public int PurchaseYear { get; set; } public int VehicleId { get; set; } public virtual Vehicle VehicleOwned { get; set; } }
View Model
public class VehicleList { public int Id { get; set; } public VehicleMake Make { get; set; } public VehicleModel Model { get; set; } [UIHint("Owners")] public List Owners { get; set; } public string Color { get; set; } public int Year { get; set; } }
The Goal
So the goal of this is to get it to work like normal model binding but submit the List<T>, in this case List<Owner> as part of the view model. The reason we are able to achieve this goal is due to how we created our editor template.
Editor Template
@model List<MVC451Sandbox.Models.Owner>; <h3>Current and Previous Owners</h3> @{ if (Model != null && Model.Count > 0) { for(int i = 0; i < Model.Count; i++) { @Html.LabelFor(m => Model[i].Name) @: @Html.EditorFor(m => Model[i].Name) @Html.HiddenFor(m => Model[i].Name) @Html.LabelFor(m => Model[i].PurchaseYear) @: @Html.EditorFor(m => Model[i].PurchaseYear) @Html.HidenFor(m => Model[i].PurchaseYear) @Html.HiddenFor(m => Model[i].Id) @Html.HiddenFor(m => Model[i].VehicleId) } } else { No previous or current owners on record. } }
We use an index (i) in our for loop. This index allows us to access a specific item in the List, and this in turn tells the model binding how to deal with the item.
The above editor template, while not the prettiest, gives us this as a result.
Here is how part of it looks in the page source.
<input class="text-box single-line" id="Owners_2__Name" name="Owners[2].Name" type="text" value="Bob Barker" />
So now when we submit it and catch it in the debugger, we see we have our List.
Summary
So there you have it, you can still use Model Binding when you have a List. While you may or may not want to use an editor or display template for your List<T>, I went that route because I felt it would be a bit easier. My editor and my display (not in this post) expect a List<T> of Owner.
Pingback: Render a View or Template Using JavaScript | Sheldon's Space