为什么默认模型绑定器不会在回发时更新我的​​局部视图模型?

时间:2010-04-09 19:54:25

标签: asp.net-mvc

我有一个类,其中包含另一个类作为其属性之一。

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

第二类只有一个属性

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

我的控制器只是抓取SiteProperties并返回视图。在提交时,它接受SiteProperties并返回相同的视图。

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

视图包含呈现ResultPageProperties模型的部分视图。

<% 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); %>

<% } %>

部分只是

<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>

好的,所以当页面呈现时,你会在两个选择中得到“Arial,...”。如果为两者选择另一个选项并单击“提交”,则活页夹将填充SiteProperties对象并将其传递给控制器​​。但是,ResultFontFamily始终包含原始值。我希望它具有用户选择的值。

我错过了什么?

4 个答案:

答案 0 :(得分:1)

这里的问题是html帮助程序的工作方式(所有这些):在尝试绑定时,它们将首先查看POST请求值,然后在模型和viewdata中提取值。这是设计的。它基本上意味着即使在你的帖子控制器操作中你试图修改值,html帮助器也不会使用它们并选择最初由用户发布的那些。

<%= Html.DropDownListFor(m => m.DropFontFamily, 
    ViewData["FontFamilyList"] as List<SelectListItem>, 
    new { Class = "UpdatesDropDownExample" })
%>

DropDownListFor帮助程序检测到ResultFontFamily的已发布值,并将使用它而不是您在控制器中提供的值。

可能的解决方法是编写自己的帮助程序。

答案 1 :(得分:0)

如果查看调试器并在

上设置断点
public SiteProperties()
{
 ***HERE***        DropFontFamily = "Arial, Helvetica, Sans-serif";
}

那么你可以看到,当你做回发时,出于某种原因,在它到达PopulateProperyDropDownLists()之前尝试使用默认构造函数;

http://ubiquitous-tech.blogspot.com/2009/05/aspnet-mvc-post-to-controllers.html

有几个关于如何处理回发部分的选项

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

似乎有效...我无法开始告诉你为什么,但

答案 2 :(得分:0)

如果我改变了将ResultPageProperties属性声明为

的方式
public ResultPageProperties ResultPagePropertyList { 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; }    
}  

post方法为null。所以活页夹似乎忽略了它。

所以我将控制器方法更改为以下功能。

[AcceptVerbs(HttpVerbs.Post)]
    public ActionResult SiteOptions(SiteProperties properties, ResultPageProperties resultPageProp)
    {
        properties.ResultPagePropertyList = resultPageProp;

        PopulateProperyDropDownLists();
        return View("SiteOptions", properties);
    }

答案 3 :(得分:0)

使用Html.EditorFor代替Html.RenderPartial。

请参阅Model binding with nested child models and PartialViews in ASP.NET MVC