0

My model is a person contains a collection of another persons(Parents). Every person have a collection of contacts.

Edit.cshtml

@model Person
@using (Html.BeginForm("Save", "", FormMethod.Post, ...))
{
    @foreach (var parent in Model.Parents)
    {
        Html.RenderPartial("ParentItem", parent);
    }
    @foreach (var contact in Model.Contacts)
    {
        Html.RenderPartial("ContactItem", contact);
    }
    \\other 
}

ContactItem.cshtml

@model Contact
@using (Html.BeginCollectionItem("Contacts"))
{
    @Html.HiddenFor(model => model.Id)
    \\other 
}

ParentItem.cshtml

@model Person
@using (Html.BeginCollectionItem("Parents"))
{
    @Html.HiddenFor(model => model.Id)
    @foreach (var contact in Model.Contacts)
    {
        Html.RenderPartial("ContactItem", contact);
    }
    \\other 
}

The problem appears when I add a new parent to a person (Person.Parents.first now exists), then add a Contact to a parent(Person.Parents.first.Contacts.first expected), model comes to "Save" inside an outer collection (Person.Contacts.last my new contact here) I think it is connected with naming of collections on the form(BeginCollectionItem("Contacts")), but how to solve it?

Xavr
  • 229
  • 1
  • 13
  • 1
    `BeginCollectionItem` will not work with nested collections. –  Jun 28 '17 at 13:36
  • 1
    [this article](http://www.joe-stevens.com/2011/06/06/editing-and-binding-nested-lists-with-asp-net-mvc-2/) might be useful, otherwise you can do this all client side with javascript - refer [this DotNetFiddle](https://dotnetfiddle.net/wqE6Rb) for an example –  Jun 28 '17 at 13:40
  • @StephenMuecke ty, article example works perfectly for me. Your client side solution is also good – Xavr Jun 29 '17 at 08:33

1 Answers1

0

Instead of PartialViews you should use EditorTemplates like this:

Edit.cshtml

@model Person
@using (Html.BeginForm("Save", "", FormMethod.Post, ...))
{
    @Html.EditorFor(x => x.Parents)
    @Html.EditorFor(x => x.Contacts)
    \\other 
}

In Views/Shared/EditorTemplates folder create 2 views:

Contact.cshtml

@model Contact

@Html.HiddenFor(model => model.Id)
\\other 

Person.cshtml

@model Person

@Html.HiddenFor(model => model.Id)
@Html.EditorFor(x => x.Contacts)
\\other 

Then you won't have any problems with naming becouse EditorTemplates feature will do this for you.

teo van kot
  • 12,350
  • 10
  • 38
  • 70
  • 1
    OP wants to dynamically add new items in the view (hence `BeginCollectionItem`) which will not work with an `EditorTemplate` –  Jun 29 '17 at 04:40
  • @StephenMuecke oops, you right. Then i just need to add templates approach to this answer like you use in your comment link. Also i always wondering if i need not only add, but also dynamic delete function how should i use your approach? I mean there is a trouble with index, if you delete record in the middle – teo van kot Jun 29 '17 at 07:59
  • Not using `BeginColletionItem()` - its adds an collection indexer based on a `Guid` and a hidden input for the indexer which allow non-zero based, non-consecutive collections to be bound. And for a client side only solution, see the fiddle I linked to (and for a simple example - refer [this answer](https://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308)) –  Jun 29 '17 at 08:04