Why doesn't the default model binder update my partial view model on postback?

Posted by bdnewbe on Stack Overflow See other posts from Stack Overflow or by bdnewbe
Published on 2010-04-09T19:54:24Z Indexed on 2010/04/09 21:43 UTC
Read the original article Hit count: 221

Filed under:

I have a class that contains another class as one of its properties.

public class SiteProperties
{
    public SiteProperties()
    {
        DropFontFamily = "Arial, Helvetica, Sans-serif";
    }
    public string DropFontFamily { get; set; }

    private ResultPageProperties m_ResultPagePropertyList;
    public ResultPageProperties ResultPagePropertyList
    {
        get
        {
            if (m_ResultPagePropertyList == null)
                m_ResultPagePropertyList = new ResultPageProperties();
            return m_ResultPagePropertyList;
        }
        set { m_ResultPagePropertyList = value; }
    }
}

The second class has just one property

public class ResultPageProperties
{
    public ResultPageProperties()
    {
        ResultFontFamily = "Arial, Helvetica, Sans-serif";
    }
    public string ResultFontFamily { get; set; }
}

My controller just grabs the SiteProperties and returns the view. On submit, it accepts SiteProperties and returns the same view.

public class CompanyController : Controller
{
    public ActionResult SiteOptions(int id)
    {
        SiteProperties site = new SiteProperties();
        PopulateProperyDropDownLists();
        return View("SiteOptions", site);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult SiteOptions(SiteProperties properties)
    {
        PopulateProperyDropDownLists();
        return View("SiteOptions", properties);
    }

    private void PopulateProperyDropDownLists()
    {
        var fontFamilyList = new List<SelectListItem>();
        fontFamilyList.Add(new SelectListItem() { Text = "Arial, Helvetica, Sans-serif", Value = "Arial, Helvetica, Sans-serif" });
        fontFamilyList.Add(new SelectListItem() { Text = "Times New Roman, Times, serif", Value = "Times New Roman, Times, serif" });
        fontFamilyList.Add(new SelectListItem() { Text = "Courier New, Courier, Monospace", Value = "Courier New, Courier, Monospace" });
        ViewData["FontFamilyList"] = fontFamilyList;
    }
}

The view contains a partial view that renders the ResultPageProperties Model.

<% using (Html.BeginForm("SiteOptions", "Company", FormMethod.Post))
   {%>

    <p><input type="submit" value="Submit" /></p>
    <div>View level input</div>
    <div>
        <label>Font family</label><br />
        <%= Html.DropDownListFor(m => m.DropFontFamily, ViewData["FontFamilyList"] as List<SelectListItem>, new { Class = "UpdatesDropDownExample" })%>
    </div>

    <% Html.RenderPartial("ResultPagePropertyInput", Model.ResultPagePropertyList); %>

<% } %>

The partial is just

<div style='margin-top: 1em;'>View level input</div>
<div>
    <label>Font family</label><br />
    <%= Html.DropDownListFor(m => m.ResultFontFamily, ViewData["FontFamilyList"] as List<SelectListItem>, new { Class = "UpdatesResultPageExample" })%>
</div>

OK, so when the page renders, you get "Arial, ..." in both selects. If you choose another option for both and click submit, the binder populates the SiteProperties object and passes it to the controller. However, the ResultFontFamily always contains the original value. I was expecting it to have the value the user selected.

What am I missing?

© Stack Overflow or respective owner

Related posts about asp.net-mvc