需要帮助将DefaultModelBinder用于嵌套模型

时间:2010-04-01 21:03:23

标签: asp.net-mvc-2 defaultmodelbinder

有一些相关的问题,但我找不到有效的答案。

假设我有以下型号:

public class EditorViewModel
{
  public Account Account {get;set;}
  public string SomeSimpleStuff {get;set;}
}

public class Account
{
  public string AccountName {get;set;}
  public int MorePrimitivesFollow {get;set;}
}

以及扩展ViewPage<EditorViewModel>的视图,该视图执行以下操作:

<%= Html.TextBoxFor(model => model.Account.AccountName)%>
<%= Html.ValidationMessageFor(model => model.Account.AccountName)%>
<%= Html.TextBoxFor(model => model.SomeSimpleStuff )%>
<%= Html.ValidationMessageFor(model => model.SomeSimpleStuff )%>

我的控制器看起来像:

[HttpPost]
public virtual ActionResult Edit(EditorViewModel account)
{ /*...*/ }

如何让DefaultModelBinder正确绑定我的EditorViewModel?没有做任何特别的事情,我得到了一个我的EditorViewModel的空实例,其中包含所有null或默认值。

我最接近的是手动拨打UpdateModel

[HttpPost]
public virtual ActionResult Edit(EditorViewModel account)
{
    account.Account = new Account();
    UpdateModel(account.Account, "Account");
    // this kills me:
    UpdateModel(account);

这成功更新了我的帐户属性模型,但当我在account上调用UpdateModel(以获取我的EditorViewModel的其余公共属性)时,我得到了完全无益的“类型的模型......不能得到更新。“没有内在的例外,所以我无法弄清楚出了什么问题。

我该怎么办?

1 个答案:

答案 0 :(得分:4)

粘合剂变得混乱,因为它看到您的操作方法的参数名为 account ,并且它看到名为 account.accountname 的传入表单字段,所以它正在查找对于EditorViewModel上的AccountName属性。

您可以通过将参数重命名为与传入表单字段不冲突的其他内容来解决此问题,或者您可以在参数上粘贴[Bind(Prefix =“”)]属性。该属性说“忽略参数名为 account 的事实,并假装我给它一个空字符串名称。”然后,活页夹将查找 account.accountname 而不是 account.account.accountname

修改 - 更多信息:

当绑定器看到名为 foo 的复杂参数时,它会查看名为* foo。**的任何内容的当前请求。因此,如果您的参数名为 foo 且其类型具有名为 FirstName 的属性,则传入的值应为 foo.FirstName = John ,例如。

但是,如果绑定器没有看到* foo。**作为请求的一部分,它只是直接查找*(没有 foo 前缀)。因此,只要请求中没有* foo。**,您就可以提交 FirstName = John ,并且活页夹会正确理解这一点。但是如果请求中有* foo。**,那么 FirstName = John 值将与FirstName属性不匹配。

现在您可以看到如何为您的操作方法提供与其属性相同的名称将会抛弃此逻辑。