Sunday, June 28, 2015

ASP.NET MVC Create Editable Views for Collections

In this post, I want to focus on a few common mistakes when creating editable views for collections in ASP.NET MVC. These mistakes are related to the ASP.NET MVC wiere format and are pretty common and a new ASP.NET MVC programmer can spend hours trying to figure out what's wrong.

If you are new to ASP.NET MVC wire format, here is a quick primer - It is basically about how your model or viewmodel collection objects are rendered in the views. Let's say you have the following class -

public class Person 
public int Id {get;set;}
public string Name {get;set;}

Your Controller would look like -

public ActionResult PersonAction(Person[] employeeList) { ... }

Your View takes an IEnumerable of the Person class and looks like the below -
@model IEnumerable<Person>

Now, this Person collection/array
Person employeeList[] = new Person[] {new Person() {Id=1, Name="person1" }, new Person() {Id=2, Name="person2"} }; 

should show up as below in the rendered HTML -
<input type='hidden' value='0' name='employeeList.Index'/>

<input type='text' value='1' name='employeeList[0].Id' />

<input type='text' value='person1' name='employeeList[0].Name' />
<input type='hidden' value='1' name='employeeList.Index'/>

<input type='text' value='2' name='employeeList[1].Id' />
<input type='text' value='person2' name='employeeList[1].Name' />

Note: This hidden index element is needed in case your list is unordered. For example, if your View supports deletion and addition of new collection items then the indexing can get out of order in a hurry.

So, what are the most overlooked things that might save you hours of debugging? Here goes -

  1. The "name" attribute of your HTML elements that render the collection properties must have the
    ActionParameterName.PropertyName signature
    So, if your controller action method looks like
    public ActionResult GetList(Person[] employeeList)

    and a property of the Person class is Id, then the name of the input elements must be like
    <input type='text' value='1' name='employeeList[0].Id' />

    (As in the the underlined parts). And it goes without saying that this naming convention will be used for all properties that are to be rendered.
  2. The name of the hidden "index" element must have the ActionParameterName.Index signature - Again, if your controller action method looks like
    public ActionResult GetList(Person[] employeeList
    then the name of the hidden index element will be like
    <input type='hidden' value='0' name=&#39employeeList.Index'/>

  3. The index of all array elements must be same as the value of the hidden "index" element - So, for rendering the first element of the employeeList array (the index is zero), the hidden "index" element will look like
    <input type='hidden' value='0' name='employeeList.Index'/> 

    (notice the value is 0) and the element that render the property Id will look like
    <input type='text' value='1' name='employeeList[0].Id' />

No comments:

Post a Comment