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

I'm new to .NET together, be patient with me if I get any stupid mistakes.

I am using ASP.NET MVC 3 with .NET 4.0

I want to have a Create view for a model with a child model. This view should include the partial Create model, I will use the following simple example to illustrate:

  • Person Model

    class Person { public string Name { get; set; } public Address { get; set; } } 
  • Model Address

     class Address { public string City { get; set; } public string Zip { get; set; } //A List for creating a <select/> item in the view //containing cities fetched from the database. //The initialization is done in the controller action returning //the related partial view. public IEnumerable<SelectListItem> CityDropDown { get; set; } ) } 
  • Controller Actions

      class MyController : Controller { public ViewResult Create() { var person = new Person(); var address = new Address(); // initialization of address.CityDropDown omitted person.Address = address; return View(MyViews.CreatePersonView, person); } [HttpPost] public ViewResult Create(Person person) { //persistance logic } } 
  • The view hierarchy I want to have:

Person Create View Hierarchy

The solutions I tried to achieve this are as follows:

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


What I've done:

  • Person view

     @model Person @using(Html.BeginForm()){ @Html.EditorFor(m=>m.Name) @Html.Partial(MyViews.AddressPartialView, @Model.Address) } 
  • Partial View Address

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

Problem:

When the form is person.Address is null. After a short search on Google, I found out that in order to send an address field, the generated HTML markup should be as follows (note 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 does not match in my case, but instead (the Address_ prefix Address_ missing):

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

Second approach: using the EditorTemplate for the Address model


What I've done:

  • I moved the partial view Address to the View / Shared / EditorTemplates folder , indicating that it has the same name as the Address property in Person , i.e. Address.cshtml .

  • Person view

     @model Person @using(Html.BeginForm()){ @Html.EditorFor(m=>m.Name) @Html.EditorFor(@Model.Address) //will automatically find the Address //partial view in the EditorTemplates folder } 

Problem:

Using this approach, the generated markup is actually the proper prefix (i.e. Address_ ), but I get an Object link not set to exclude the instance for the Address.CityDropDown property, which tells me that the pre-initialized address object in the controller action for what - Either the reason is not transferred to a partial view.

Third approach: put all the Address fields in the Person model


This approach works without problems, but I do not want to use it, because I do not want to have redundant code if I ever want to create a view representation for an address in another model.

Summarizing


What should I do to have a partial reusable creation that I can use in my application?

+6
source share
1 answer

You had the right approach with EditorTemplates, but keep in mind that you need to populate CityDropDown . Thus, the view should be passed something like this:

 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" } } } }; 

To make this view consist only of:

 @Html.EditorForModel() 

And then your EditorTemplates would pick up from there:

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

 @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 display 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" /> 

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

+3
source

Source: https://habr.com/ru/post/955488/


All Articles