So I want to create a re-usable view for editing an Address, phone number, etc.
I setup a Container Model that contains all the Models needed. Created a partial view to handle the Address part of th e form
But when it posts back to the controller, customer data is there from the main page, but anything from the partial views is not there (using MVC4/Razor)
Container Model
public class CustomerViewModel {
public Customer CustomerData { get; set; }
public Address MainAddress { get; set; }
public Address ShippingAddress { get; set; }
public Phone MainPhone { get; set; }
public Phone Fax { get; set; }
}
Controller:
public ActionResult Edit(int id = 0) {
CustomerViewModel model = new CustomerViewModel();
model.CustomerData = Customer.FetchById(id);
if (model.CustomerData == null) return HttpNotFound();
//... load addresses, phones
return View(model);
}
[HttpPost]
public ActionResult Edit(CustomerViewModel model) {
if (ModelState.IsValid) {
///... save everything here - model has CustomerData, but nothing else
}
return View(model);
}
Main View:
@model ProjectName.WebSite.Models.CustomerViewModel
.....
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Customer</legend>
@Html.HiddenFor(model => model.ModelCustomer.CustomerId)
<div class="editor-label">
@Html.LabelFor(model => model.ModelCustomer.CompanyName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ModelCustomer.CompanyName)
@Html.ValidationMessageFor(model => model.ModelCustomer.CompanyName)
</div>
...
@Html.Partial("Address", Model.MainAddress, new ViewDataDictionary {
TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "Main" }
})
...
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
.....
Address Partial View:
@model ProjectName.Business.Address
<fieldset style="margin-top: 20px;">
<legend>@(ViewData["label"] ?? "Address")</legend>
@Html.HiddenFor(model => model.AddressId)
<div class="editor-label">
@Html.LabelFor(model => model.Street)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Street)
@Html.ValidationMessageFor(model => model.Street)
</div>
...
</fieldset>
What am I doing wrong here - why can I not get the Model populated from the partial views?
SOLVED IT! I figured it out! Could not sleep, and just stumbled on it!
In the View you have to make sure that the HtmlFieldPrefix uses the same name as in your composite model class, so since I named the two addresses as "MainAddress" and "ShippingAddress" - just have to make sure the same name is used when setting up the Partial:
@Html.Partial("Address", Model.MainAddress, new ViewDataDictionary(Html.ViewDataContainer.ViewData) {
TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "MainAddress" }
})
@Html.Partial("Address", Model.ShippingAddress, new ViewDataDictionary(Html.ViewDataContainer.ViewData) {
TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "ShippingAddress" }
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With