snajahi
snajahi

Reputation: 910

Master-Detail Create Views with Razor, ASP.NET MVC 3 and .NET 4.0

I'm new to .NET all together, please be patient with me if I have any silly mistakes.

I'm using ASP.NET MVC 3 with .NET 4.0

I want to have a "Create" view for a model that has a child Model. This view should include the child model's partial "Create" view, I'll use the following simple example for illustration purposes:

Person Create View Hierarchy

The solutions that I have tried in order to achieve this are the following :

First approach : Using @Html.Partial(..) or @{Html.RenderPartial(..)}


What I did :

The problem :

When submitting the form, person.Address is null. After a bit of searching on Google, I found out that in order for the submit of the address field to work, the generated HTML markup must be the following (notice the Address_ prefix) :

<form...>
    <input type=text id="Name" />
    <input type=text id="Address_Zip" />
    <select id="Address_City">
        <!-- options... -->
    </select>
</form>

Needless to say, the generated HTML markup in my case isn't the same but instead it's the following (the Address_ prefix is missing) :

<form...>
    <input type=text id="Name" />
    <input type=text id="Zip" />
    <select id="City">
        <!-- options... -->
    </select>
</form>

Second approach : Using an EditorTemplate for the Address model


What I did :

The problem :

Using this approach the generated markup has in fact the proper prefix (i.e. Address_), but I get an Object reference not set to an instance exception for the Address.CityDropDown property which tells me that the pre-initialised Address object in the controller's action isn't passed to the partial view for some reason.

Third approach : put all Address fields in the Person model


This approach works with no problems, but I don't want to use it as I don't want to have redundant code if I ever want to have a create view for address in another model.

To sum up


What should I do in order to have a reusable partial create view that I can use accross my application?

Upvotes: 6

Views: 13873

Answers (1)

Brad Christie
Brad Christie

Reputation: 101614

You had the correct approach with EditorTemplates, but keep in mind you need to populate the CityDropDown. So, the view should be handed off something like:

Person model = new Person()
{
    Address = new Address
    {
        CityDropDown = new SelectListItem[]{
            new SelectListItem { Selected = true, Text = "Select one..." },
            new SelectListItem { Text = "Anywhere", Value = "Anywhere" },
            new SelectListItem { Text = "Somewhere", Value = "Somewhere" },
            new SelectListItem { Text = "Nowhere", Value = "Nowhere" }
        }
    }
};

Which would then make this view only consist of:

@Html.EditorForModel()

And then your EditorTemplates would pick up from there:

~/Views/shared/EditorTemplates/Address.cshtml (Note: this is based on type not property name)

@model MvcApplication.Models.Address
@Html.DropDownListFor(x => x.City, Model.CityDropDown)
@Html.EditorFor(x => x.Zip)

~/Views/Shared/EditorTemplates/Person.cshtml

@model MvcApplication.Models.Person
@using (Html.BeginForm())
{ 
    @Html.EditorFor(x => x.Name)
    @Html.EditorFor(x => x.Address)
    <input type="submit" value="Save" />
}

the three views then render something like:

<form action="/" method="post">
  <input class="text-box single-line" id="Name" name="Name" type="text" value="" />
  <select id="Address_City" name="Address.City">
    <option selected="selected">Select one...</option>
    <option value="Anywhere">Anywhere</option>
    <option value="Somewhere">Somewhere</option>
    <option value="Nowhere">Nowhere</option>
  </select>
  <input class="text-box single-line" id="Address_Zip" name="Address.Zip" type="text" value="" />
  <input type="submit" value="Save" />

Example project can be found here: https://github.com/bchristie/StackOverflow-Examples/tree/master/questions-19247958

Upvotes: 3

Related Questions