复杂对象和模型绑定器 ASP.NET MVC

Complex object and model binder ASP.NET MVC

我有一个带有 Foo class 的模型对象结构,其中包含一个带有字符串值的 Bar

public class Foo
{
    public Bar Bar;
}

public class Bar
{
    public string Value { get; set; }
}

以及像这样使用该结构的视图模型

public class HomeModel
{
    public Foo Foo;
}

然后我有一个表单,在 Razor 中看起来像这样。

<body>
    <div>
        @using (Html.BeginForm("Save", "Home", FormMethod.Post))
        {
            <fieldset>
                @Html.TextBoxFor(m => m.Foo.Bar.Value)
                <input type="submit" value="Send"/>
            </fieldset>
        }

    </div>
</body>

在html中变成。

<form action="/Home/Save" method="post">
    <fieldset>
        <input id="Foo_Bar_Value" name="Foo.Bar.Value" type="text" value="Test">
        <input type="submit" value="Send">
    </fieldset>
</form>

控制器终于可以像这样处理 post 厕所了

[HttpPost]
public ActionResult Save(Foo foo)
{
    // Magic happends here
    return RedirectToAction("Index");
}

我的问题是 Foo 中的 Bar 一旦遇到 Save 控制器操作(Foo 已创建但带有 null Bar 字段).

我认为 MVC 中的模型绑定器可以创建 FooBar 对象并设置 Value 属性,只要它看起来像以上。我错过了什么?

我也知道我的视图模型有点过于复杂并且可以更简单,但是对于我正在尝试做的事情,如果我可以使用更深层次的对象结构,我真的会帮助我。上面的例子使用 ASP.NET 5.

首先,DefaultModelBinder 不会绑定到字段,因此您需要使用属性

public class HomeModel
{
  public Foo Foo { get; set; }
}

其次,助手正在生成基于 HomeModel 的控件,但您回发到 Foo。将 POST 方法更改为

[HttpPost]
public ActionResult Save(HomeModel model)

或使用 BindAttribute 来指定 Prefix(这实质上是从发布的值中剥离前缀的值 - 所以 Foo.Bar.Value 变成 Bar.Value绑定)

[HttpPost]
public ActionResult Save([Bind(Prefix="Foo")]Foo model)

另请注意,您不应将方法参数命名为与您的某个属性同名,否则绑定将失败并且您的模型将为空。

我刚刚发现发生这种情况的另一个原因,那就是如果您的 属性 被命名为 Settings!考虑以下视图模型:

public class SomeVM
{
    public SomeSettings DSettings { get; set; } // named this way it will work

    public SomeSettings Settings { get; set; } // property named 'Settings' won't bind!

    public bool ResetToDefault { get; set; }
}

在代码中,如果您绑定到 Settings 属性,它将无法绑定(不仅在 post 上,甚至在生成表单时也是如此)。如果您将 Settings 重命名为 DSettings (等等),它突然又可以工作了。

我遇到了同样的问题,在我按照@Stephen Muecke 的步骤进行操作后,我意识到问题是因为我的输入被禁用了(我在准备好文档时使用 JQuery 禁用了它们),如您所见这里:How do I submit disabled input in ASP.NET MVC?。最后我使用只读而不是禁用属性,所有值都成功发送到控制器。

我遇到了同样的问题,但是一旦我为外键创建了一个隐藏字段...一切正常...

表格示例:

@using (Html.BeginForm("save", "meter", FormMethod.Post))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    @Html.HiddenFor(model => Model.Entity.Id)
    @Html.HiddenFor(model => Model.Entity.DifferentialMeter.MeterId)
    @Html.HiddenFor(model => Model.Entity.LinearMeter.MeterId)
    @Html.HiddenFor(model => Model.Entity.GatheringMeter.MeterId)

    ... all your awesome controls go here ...
}

动作示例:

// POST: /Meter/Save
[HttpPost]
public ActionResult Save(Meter entity)
{
    ... world-saving & amazing logic goes here ...
}

美图: