Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC4 Partial view not loading values into "container" model on post back

Tags:

asp.net-mvc

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?

like image 554
Nayt Grochowski Avatar asked May 20 '12 07:05

Nayt Grochowski


1 Answers

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" }
})
like image 54
Nayt Grochowski Avatar answered Nov 17 '22 05:11

Nayt Grochowski