3

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

假设我有以下模型:

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 account(以获取我的 EditorViewModel 的其余公共属性)时,我得到完全没有帮助的“类型的模型......无法更新”。没有内部异常,所以我无法弄清楚出了什么问题。

我该怎么办?

4

1 回答 1

4

活页夹感到困惑,因为它看到您的操作方法的参数名为account ,并且它看到名为account.accountname的传入表单字段,因此它正在您的 EditorViewModel 上寻找 AccountName 属性。

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

编辑 - 更多信息:

当 binder 看到一个名为foo的复杂参数时,它会查看当前对任何名为 *foo.** 的请求的请求。因此,如果您的参数被命名为foo并且它的类型有一个名为FirstName的属性,那么传入的值应该是foo.FirstName=John,例如。

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

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

于 2010-04-01T23:16:43.690 回答