1

I am working on ASP.NET MVC 4 application. I use EF 5 and Code First. I have two entities with 1:N relation:

public class Menu
{
    //some properties
    public virtual ICollection<Document> Documents { get; set; }
}

and:

public class Document
{
//some properties..
public int MenuID { get; set; }
public virtual Menu Menu { get; set; }
}

I have Edit view with [HttpPost] and [HttpGet] methods. When I pass the model through the GET action like this :

                Menu model = unitOfWork.MenuRepository.GetById(Id);
                if (model != null)
                {
                    return View(model);
                }

everything is right, I can see that model contains 1 Documents but then in my razor view if I simply try:

@Html.HiddenFor(m => m.Documents)

then when I submit the form to the Post action I can see that the Documents property is null.

How can keep Documents persistent?

Leron
  • 9,546
  • 35
  • 156
  • 257

2 Answers2

2

Anything with a collection will not get rendered as you are expecting. you need to create say, a displaytemplate which expects a collection and then render our the properties of the documents in a HiddenFor or if you dont want a display template then do the same but on the view in question.

for example, this is what you need to do:

@for(int counter = 0; counter < Model.Documents; counter++)
{
   @Html.HiddenFor(m => Model.Documents[counter].Id)
   @Html.HiddenFor(m => Model.Documents[counter].Title)
   // and so on
}

so now when you postback, it has all the properties it needs for the engine to bind to and pass it to your controller method and serve it up.

Ahmed ilyas
  • 5,722
  • 8
  • 44
  • 72
  • Well, I tried this just for the sake of it. First - it seem one cannot use `[]` indexer for `ICollection` and second, even if I change the type in the entity to something else it's still not a very elegant solution. – Leron Dec 07 '13 at 20:11
  • hey @Leron - Sorry, I had in my mind you werent using the ICollection but part of my brain was saying "yes he is, he said so in the title". The solution may not be elegant but this is how to do it. I was in the same ship as you a while back and this worked. Even better is to have this code but in a Display or Editor template so you just reference it instead and let the templates do the work instead. you could ToList() instead to give you indexer ability – Ahmed ilyas Dec 07 '13 at 20:14
  • just to add, you really do need the indexer otherwise the MVC engine will not be able to bind back correctly. Infact it won't do. This is how the engine works. I tried numerous ways before and this was the only way - I also had read a blog post (cant remember which at the moment) that confirmed the same thing. – Ahmed ilyas Dec 07 '13 at 20:15
  • yeah indeed indexer is needed, but I'm not sure, I tried the example from the aershov post and Darin's one is working and need less code writing. To be honest I'm not sure which one to pick. – Leron Dec 07 '13 at 20:27
  • whichever works for you I guess. :) For me, the approach I took not only works but is somewhat more JQuery friendly too. Like I said, create a display and editor for template and slap in the code. Then wherever you want to display it/edit it, just use the editor template and pass in the collection in question. Job done – Ahmed ilyas Dec 07 '13 at 20:34
1

Have you looked through the html, that is generated ? Take a look )

This answer and this one provide workarounds.

Community
  • 1
  • 1
Andrey Ershov
  • 1,773
  • 1
  • 16
  • 26