5

I have a collection of objects on my Model that I'm rendering in a View by using EditFor function, and I have an EditorTemplate which is responsible for actually rendering each object.

@Html.EditorFor(model => model.MyObjects)

This has worked well for a while now, and when you check the html, my text boxes are prefixed with the model property, followed by the index of the collection they came from.

<input class="text-box single-line" id="MyObjects_2__SomeProperty" 
name="MyObjects[2].SomeProperty" type="Text" value="" />

However I've recently started using the ShowForEdit and ShowForDisplay properties in the model metadata for the collection, and in the first line of my editor template if the ShowForEdit is not true, I just skip it.

@if (!ViewData.ModelMetadata.ShowForEdit)
{
    return;
}

But because these are all indexed in the html, when I try to save this collection back to the viewmodel via a postback, it fails because of a reliance on the indexing numbers. Every item in the collection after the missing index is missing from my view model when I check it's value.

In this case it's actually my first item in the collection that I'm skipping since I don't want it to be visible on the edit view, but because of this when I postback the first index in the html is 1 (instead of 0 like it normally would be), but this is a problem when you try to save the changes. This is also a problem when altering the DOM using javascript.

Has anyone else encountered a problem with the default model binder's ability to read data posted back when one or more indexes in the html represented collection are not present?

Are there model binders that handle this problem?

Nick Albrecht
  • 16,607
  • 10
  • 66
  • 101
  • For [tag:asp.net-mvc-3] I would recommend looking at [MVC3 Non-Sequential Indices and DefaultModelBinder](http://stackoverflow.com/questions/8598214/mvc3-non-sequential-indices-and-defaultmodelbinder). Basically, just add a hidden field (per collection item) with the special `MyCollection.Index` name with the index as the value. – Joel Purra Apr 03 '12 at 14:32

2 Answers2

2

Ran into this issue recently and solved it by converting the List to a Dictionary<string, model> with GUIDs as the key.

@foreach (var index in Model.EmailAddresses.Keys)
{
    <label asp-for="@Model.EmailAddresses[index].Email">Email</label>
    <input asp-for="@Model.EmailAddresses[index].Email" type="text" />
}

This avoided having to include hidden inputs that map to the index value.

nelowe
  • 66
  • 1
  • 6
  • This may not work with older versions of asp.net-mvc, which is what I was using at the time when I originally encountered this problem. It's quite possible that newer versions (or even asp.net-core) have simplified this, but I haven't tried removing the `Index` property to see. It's also worth noting using the helper method like described in the links suggested has the added benefit of cascading the view model traversal down the chain so that EditorTemplates, DisplayTemplates, etc, all work with it. Where as you've explicitly had to specify the index. – Nick Albrecht Oct 14 '20 at 23:52
0

There are some very good blog posts that allow you to modelbind to a list without the need to provide zero based contiguous index. plz have a look at http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
http://zahidadeel.blogspot.com/2011/05/master-detail-form-in-aspnet-mvc-3-ii.html
Furthermore, if you are interested in MVVM pattern and knockout js you can check this great work by steve sanderson
For more reading put "editing varibale length list mvc style" in google and it will give u a dozen useful links

Muhammad Adeel Zahid
  • 17,474
  • 14
  • 90
  • 155
  • I sorted through a few of the links you provided but most of them reply on a few small samples of code and the rest is included in a larger project download which you have to sift through to find the relevant bits, which personally I find very annoying. I did however modify your suggested search terms and found this posting which has helped. [link](http://ivanz.com/2011/06/16/editing-variable-length-reorderable-collections-in-asp-net-mvc-part-1/) Ironically this is very close to how I had done this in MVC2 but then discovered the support for auto generated indexes and ended up using it instead – Nick Albrecht Jul 28 '11 at 16:19