0

I am trying to create a form which allows the creation and editing of a hierarchy of entities using MVC.

The top level is project which can have 1 or many environments associated with it. The environments are predefined, eg Dev, Test and Prod.

For each environment that is added it is possible to add several interfaces.

So a user would enter the project information. Select which environments which are relevant and then for each environment section add several interfaces.

I've created 3 view models, project, environment and interface. Like so

public class ProjectViewModel
{
    public int Id { get; set; }
    public string ProjectTitle { get; set; }
    public List<SelectListItem> EnvironmentChoices { get; set; }
    public List<EnvironmentViewModel> EnvironmentModel { get; set; }
}

public class EnvironmentViewModel
{
    public IList<InterfaceViewModel> Interfaces { get; set; }
    public string Environment { get; set; }
}

public class InterfaceViewModel
{
    public string InterfaceName { get; set; }
}

Then created 1 project template and 2 editor templates for the environment model and the interface model.Like so

<p>
    @Html.LabelFor(x => x.ProjectTitle)
    @Html.TextBoxFor(x => x.ProjectTitle)
    @Html.ValidationMessageFor(x => x.ProjectTitle)
</p>
<p>
    @Html.LabelFor(x => x.EnvironmentModel)

    @for (int i = 0; i < Model.EnvironmentChoices.Count; i++)
    {
        @Html.CheckBoxFor(m => m.EnvironmentChoices[i].Selected, new { id = Model.EnvironmentChoices[i].Value })
        @Html.HiddenFor(m => m.EnvironmentChoices[i].Value)
        @Html.DisplayFor(m => m.EnvironmentChoices[i].Text)
    }
</p>
<p>
    @Html.EditorFor(x => x.EnvironmentModel)
</p>

for the environment template

@model EnvironmentViewModel
<fieldset style="margin-left: -10px;">
    <legend>@Model.Environment</legend>
    @Html.ActionLink("Add Interface", "AddInterface", Model, new { @class = "button icon-file-plus" })
    @Html.EditorFor(x => x.Interfaces)
</fieldset>

for the interface template

@model InterfaceViewModel
<p>
    @Html.LabelFor(x => x.InterfaceName)
    @Html.TextBoxFor(x => x.InterfaceName)
    @Html.ValidationMessageFor(x => x.InterfaceName)
</p>

What I am finding is that when I click the add button on the environment section. The controller only picks up the environment model and loses the project model context so cannot modify it to add the new interface model.

Am I going about this in the wrong way? If so, are there examples of best practice. If not, what am I doing wrong.

Thanks

Richard Ev
  • 52,939
  • 59
  • 191
  • 278
mattbloke
  • 1,028
  • 1
  • 12
  • 26
  • You should not be trying to pass `EnvironmentViewModel` as route parameters in the `ActionLink` (and in any case the `Interfaces` property will be `null`). You can pass additional values (say the `project.id` value) to the template using `additionalViewData` and then pass that as a route value in the link. –  Mar 12 '15 at 10:48
  • On the create form the project hasn't been created yet so it won't have an id. I'm trying to create all the entities at once. – mattbloke Mar 12 '15 at 10:57
  • So are you wanting to dynamically add new `InterfaceViewModel` objects and then POST everything back an once (i.e save the project, get its new ID, then save the associated child objects)? –  Mar 12 '15 at 10:59
  • That was the way I had planned to do it. Is there an easier way? – mattbloke Mar 12 '15 at 11:02
  • 1
    You will need to use javascript/jquery to dynamically add the new items. A couple of options are discussed in [this answer](http://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308) –  Mar 12 '15 at 11:05
  • Thanks, that's very helpful. I also found this which is pretty close to what I'm try to do. http://jarrettmeyer.com/post/2995732471/nested-collection-models-in-asp-net-mvc-3 – mattbloke Mar 13 '15 at 14:07

1 Answers1

0

Thanks to Stephen Muecke for pointing me in the right direction.

I found this example to be very close to what I was trying to achieve

http://jarrettmeyer.com/post/2995732471/nested-collection-models-in-asp-net-mvc-3

Basically it uses to MVC to dynamic render JavaScript which in turn will add a detail view model to the form which conforms to the MVC indexing convention. Therefore when the master model and sub models are posted back the whole thing is bound to one big hierarchical model.

mattbloke
  • 1,028
  • 1
  • 12
  • 26