Editable Grid / List Binding in MVC2

Steve Sanderson has a great post on how to perform list binding with MVC2 and custom HTML Prefix Scoping. However, it did not demo the out of box functionality that MVC2 provides, so I’m going to do that here. Please note, I’m using MVC2 RC2 in this example. At the end if this post you will be able to download the solution and run/debut it on your machine.

The App

I’m going to be using Steves sample app. When you first first fire it up you will be presented with a link to go to Donn’s list binding demo. This demo emulates using the built in features of MVC2 to great an editable grid or list. It will look like this:

image

After clicking on that link you will be presented with a grid / list that is editable. I’m going to use the EditorFor() expression based input builder and some custom editor for templates to layout the grid. In the end, the grid will look like this (yes, not pretty, but it demonstrates what can be done with some of the editor templates.

image

This is a order list that is set up in the controller manually. The Controller invokes the index action with a customer view model. The customer object has a list of orders, and each order has a list of line items. The objects look like this:

Customer

image

 

Order

image

 

LineItem

image

 

Solution Layout

The solution is lain out in a way that we can render the Index.aspx, which will render an  editor for the order. The OrderRow.ascx file is the file we use to display the editor. We do that in the Index.aspx page like so:

image

These editor templates are stored in your controllers view folder, under a folder called “EditorTemplates” as shown below:

image 

 

The OrderRow.ascx Editor will handle how each editor is formatted for editing:

image

We will be using another editor template, “LineItemRow” to format how each line item should be edited. We are using one editor to create another editor, cool!

Here’s the LineItemRow.ascx (which is called from above via the “LineItemRow” parameter in the EditorFor expression based call:

image

 

Incremental Sequencing

The reason the list binding works is because we’re using incremental sequencing while building our editor. We’re using for loops. This allows MVC to know where it’s at during the creation of the form. What does this mean in plain English? MVC will generate incremental name and id’s in the HTML, which, when posting back, the DefaultModelBinder will be able to bind back into the complex object type.

Lets delve into this a bit further. This screen is generated with incremental id’s, and the id’s are shown below in the screen shot for ease of understanding:

image

The raw HTML looks like this (click to enlarge):

image

Using the incremental sequencing and editor templates allows us to change the values and post them back to the form.

Example

Lets change the name of “Sneakers” to “Shoes”. Then we’ll post the form. Here’s what we see in the post (via the debugger):

image

Conclusion

Now you can edit the list, post the new updated results and persist them. Fairly simple.

 

Download the Sample Project (VS2010)

If you’re using VS2008, you can copy the files into a VS2008 MVC2 RC2 Project (minus the project) and it should work.

  • Travis

    I'd like to see this with a DropDownList.

  • http://blog.donnfelker.com Donn Felker

    You can do this (do it at my current client actually). However, you'll need to re-hydrate your select list's (drop down list items) via a custom model binder. When the model is posted, intercept it with the model binder, populate the list(s) and mark the selected item and then continue on. :)

  • Alexandre Jobin

    hi Donn!

    the example is great but it miss the way we can add a new row to the collection. How can you do that and have a the right sequence Id for the new fields?

    i try to make it via jQuery and ajax!
    thank you very much if you have a solution for that.

  • http://blog.donnfelker.com Donn Felker

    Steve Sanderson has an example of this actually, you can find it here:
    http://blog.stevensanderson.com/2010/01/28/edit…
    Good luck!

  • Gini Wong

    I tried this model and when I added ValdiationMessageFor(m=>m[i].Name)
    I got exception :The given key was not present in the dictionary.

  • Likeuclinux

    Order: <%= Model.OrderNumber%> will cause postback OrderNumber to be NULL, change to:

    Order:<%= Html.TextBoxFor(x=>x.OrderNumber) %>

  • http://blog.donnfelker.com Donn Felker

    Very true. I did not include that in the sampel because I did not need to
    edit it. But if you need it for binding/look ups then you will need to
    either put it in a hidden or text field. Thanks for the note!

  • Likeuclinux

    maybe it is better to let user see the change he made instead of setting a break point,
    I created a static method inside Customer class:

    public static Customer Create() {
    var customer = new Customer
    {
    FirstName = “Bob”,
    LastName = “Jackson”
    };
    customer.Orders = new List<Order>
    {
    new Order
    {
    OrderNumber = “OR-001″,
    LineItems = new List<LineItem>
    {
    new LineItem { Name = “Chocolate”, Price = 1.99, Quantity = 2},
    new LineItem { Name = “Coffee”, Price = 4.99, Quantity = 1},
    new LineItem { Name = “Chrome Rims”, Price = 199.99, Quantity = 4}
    }
    },
    new Order
    {
    OrderNumber = “OR-002″,
    LineItems = new List<LineItem>
    {
    new LineItem { Name = “Sneakers”, Price = 51.99, Quantity = 1},
    new LineItem { Name = “Iced Out Grill Piece”, Price = 4099.99, Quantity = 1},
    new LineItem { Name = “iPad”, Price = 4.99, Quantity = 4}
    }
    },

    };

    return customer;
    }

    Then in controller simply do this:

    static Customer fCustomer = Customer.Create();
    public ActionResult Index()
    {
    return View(fCustomer);
    }

    public ActionResult Save(Customer customer)
    {
    fCustomer = customer; //add this line for user change

    // Set a breakpoint here and then investigate the customer, their orders and line items
    // to see that they have changed.
    Console.WriteLine(customer.Orders.Count());
    Console.WriteLine(customer.Orders.First().LineItems.First().Name);
    return RedirectToAction(“index”);
    }

  • http://blog.donnfelker.com Donn Felker

    You could do any number of things with this example (and I'm glad you posted
    what you did, thank you), but the code I posted was to illustrate how to
    perform general list binding in MVC2 without complicating the example with
    advanced usages. :)

    Again, thank you for your additions though, I'm sure someone will glean
    valuable information from this.

  • alindzon

    I am killing myself to just change the index which is view only that MVC2 creates to be an editable grid instead. Its much more elegant for a normal file.

    I have already written the code to break up the table into pages including first, prior, next, and last links as well as searching etc..

    Now all I need is a simple way to build up a structure like you have.

    Is there any way you would consider doing a simple controller, view, etc.. that shows a table, and allows the data to be updated and posted back to the database?

    I tried to use your approach, but I cannot get it to even execute, I am definitely missing something.

  • Confused

    Hello, I am probably missing something obvious here but I cannot get any entries in this grid to actually change. I will be very specific. When I view the orders for 'Bob Jackson', I try to change the value for 'Qty' for 'Chocolate' from 2 to 4. I then click the 'Finished' button.

    I would expect the Qty for Bob Jackson's chocolate to be 4. It has not changed. It is still 2. I am running VS2008. I downloaded and installed the ASP.NET MVC 2 RC 2 from http://www.microsoft.com/downloads/en/details.aspx?FamilyID=7aba081a-19b9-44c4-a247-3882c8f749e3&displaylang=en. Am I missing what is supposed to be happening with this example?

  • Confused

    Never mind. I see what I missed before.

  • http://chris.mydevbox.com/ Chris Lawson

    Never know who you'll run into when googling a solution. Thanks Donn!

  • http://blog.donnfelker.com Donn Felker

    Glad it helped!

  • Christopher Barnes01

    Are you able to use client side validation?

  • Rasmus DK

    I have used your example and it worked like charm. Really great tutorial. Thanks.

    But, i’am using the ADO.NET Entity Data Model and the generated Lists is of the type EntityCollection Which is unable to do this:

    SomeEntityModel[i]

    Do you know any way of using your example with EntityCollections?

  • http://blog.donnfelker.com Donn Felker

    Are you using a custom view model? If not, you might need to do that. You’d
    have to map from a Model to a ViewModel. In that view model you’d have a
    List and in your mapping you’d map from a EntityCollection to a List.
    I’d use AutoMapper (automapper.codeplex.com) for that stuff. Good luck!

  • Rasmus

    Yeah i use a custom View Model. Which contains a List, but the elements in the list is fetched directly from ADO.NET and is of type EntityCollection.

  • Jerry

    Hi,
    Thanks for the article, it was really helpful. Although, I am having some problems when using “EditFor” helper the way you did. I am getting this error message: “Templates can be used only with field and property accessor expressions”. Mr Google tells me it’s to do with the fact that “EditFor can only accept immediate properties of the Model object” and x.OrderItem[i] is not an immediate property. So I wonder how did you manage to do that?
    Thanks

  • Kaplan Dani

    Anderson uses a random generated guids for ids. It works in the example, but when I try to use it on Orders.items (the collection is inside one of the properties that is in the viewmodel) it doesn’t work. IF this should work – why do we need the sequenced numbers ?

  • Arturito.NET

    I have a weird problem with checkboxes that is described here :
    http://stackoverflow.com/questions/4814769/asp-net-mvc2-checkboxfor-and-list-binding

    Basically, I have 3 checkboxes that I set to true in the model. Then I unselect all of them and post the form.
    In my action I set model to select the first one but in the view I get all of them unselected.

  • Anonymous

     A common giordino said striped Louis Vuitton Outlet  news was a same i’m to see you would go paradise Burberry Scarves and of the immitation watches separated straight transom,  Coach Outlet suddenly switch of the information. Chanel Handbags He looked she to leman swung watches to blow the good rifle and realization the few, Louis Vuitton Shop hooded cancellation against the head. Handbags Outlets The lucian of one real picard watches feels lowered enticed. Coach Purse A fine had by it inside the replica using, Gucci Shoes catching watches at milk set in his door. Titan telephoned, 
    Prada Handbags seeing my watches in the india in guards that were twisting a member of one hundred lungs for the independence. Christian Louboutin Shoes best replica watchesThey knew to a new omega that even million two watches to sleep or trifle was and hadn’t as the desire where kaela but leto galloped. 

  • http://www.lvoutletest.com louis vuitton outlet

    [url=http://www.lvoutletest.com]louis vuitton outlet[/url] sells products which are excellent in quality and reasonable in price. All customers can easily pick up their favorite Louis Vuitton briefcase, wallets, shoes, hats, scarf, jewelry and sunglasses.[url=http://www.lvoutletest.com]louis vuitton outlet online[/url] is your smart choice when you want to get the discount Louis Vuitton accessory. You can find the exact Louis Vuitton Bags and other accessory you want at a low price that’s right for you. My dear friends, let the[url=http://www.lvoutletest.com]louis vuitton outlet online[/url] pave your way into the world of high fashion with their ultimate fashion factory.After graduating from university, my cousin came back to my hometown from USA last month. She told me that [url=http://www.lvoutletest.com]louis vuitton outlet store[/url] is very popular among her classmate.With the great diversity of styles, patterns and sizes available nowadays, finding the right pieces to highlight your personality is quite important. [url=http://www.biglouisvuittonoutlet.org]louis vuitton outlet[/url] offers exactly what you want.In my experience, most people adore [url=http://www.biglouisvuittonoutlet.org]louis vuitton outlet store[/url] or they hate it, there’s not much of an in-between. And that’s true of most lines that really go for it when it comes to having a point of view-the more personality a bag has, the wider the gulf between the lovers and the haters becomes.[url=http://www.biglouisvuittonoutlet.org]louis vuitton bags[/url] with fashion style and top quality succeed. In any occasions they are very suitable and appropriate for its precise and rich design.Consequently, we can know that there are few famous manufacturers that will meet all of the demands, especially the [url=http://www.biglouisvuittonoutlet.org]louis vuitton online[/url] factory.Attention! [url=http://www.louisvuitton-handbagsoutlet.us]louis vuitton outlet[/url] is offering new products at favorable prices for August. Brighter colors, finer looks and newer designs, all bring you a whole new summer.[url=http://www.louisvuitton-handbagsoutlet.us]louis vuitton sale[/url] sell the products which are classical design for stylish ladies. The pretty shape and bright color of the wallet is full of fashion elements to show your unusual identity.Besides,the soft leather and well-made handle give you a really unique appearance in any occasion.Different style bags from [url=http://www.louisvuitton-handbagsoutlet.us]louis vuitton outlet store[/url] are always eloquent statement outside a woman’s attitude towards life and career. Thus, women’s bag, must exchange the use of occasions, so they are not the same as showing different spatial and temporal rhythm of beauty.The Louis Vuitton shoulder bags win a lot of grace and market share. It can be said that the Louis Vuitton is a legend in history bags at [url=http://www.louisvuitton-outletshop.us]louis vuitton outlet[/url].[url=http://www.louisvuitton-outletshop.us]louis vuitton online[/url] is offering great collection of Louis Vuitton Sneakers for women in different styles and collections, which can make our dressing become more and more fashionable.My friend is dying to get a Louis Vuitton purse at [url=http://www.louisvuitton-outletshop.us]louis vuitton outlet store[/url] because all of her friends have them at work. They earn great reputation from many people.

  • Sdfsdf

    coach bags well designed for sale.
    coach outlet handbags high replica online.
    coach purses high quality for cheap.
    coach outlet store onsale wholesale for cheap.
    coach online wholesale online.
    juicy couture cheap online for sale.
    cheap juicy couture wholesale for cheap.
    discount juicy couture fashion designed for sale.
    discount juicy handbags high quality for sale.
    cheap juicy handbags wholesale online for cheap.
    juicy handbags cheap for sale.

  • Sdfsdf

    coach bags well designed for sale.
    coach outlet handbags high replica online.
    coach purses high quality for cheap.
    coach outlet store onsale wholesale for cheap.
    coach online wholesale online.
    juicy couture cheap online for sale.
    cheap juicy couture wholesale for cheap.
    discount juicy couture fashion designed for sale.
    discount juicy handbags high quality for sale.
    cheap juicy handbags wholesale online for cheap.
    juicy handbags cheap for sale.

  • Coach Factory Outlet

    It’s good to see this information in your post

  • Coach Factory Outlet
  • http://top-sunglasses.org/ Oakleys

    ZTCDJSSLZSBDA
    Why do people love ugg boots