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

时间:2015-01-29 10:12:47

标签: c# asp.net-mvc razor asp.net-mvc-5

我有一个模型对象结构,其中Foo类包含带有字符串值的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 loos

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

我的问题是Bar Foo null一旦点击Save控制器操作(Foo已创建但null Bar } Foo字段)。

我认为MVC中的模型绑定器能够创建BarValue对象并设置{{1}}属性,只要它看起来如上所示。我错过了什么?

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

4 个答案:

答案 0 :(得分:36)

首先,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)

另请注意,不应将method参数命名为与其中一个属性相同的名称,否则绑定将失败,并且您的模型将为null。

答案 1 :(得分:3)

我刚刚发现了另一个可能发生这种情况的原因,即你的财产名为Settings!请考虑以下View模型:

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(等),它会突然再次运作。

答案 2 :(得分:0)

我遇到了同样的问题,在我按照@Stephen Muecke步骤后,我意识到问题是由于我的输入被禁用(我在文档就绪时使用JQuery禁用它们)引起的,你可以在这里看到它:{{3} }。最后,我使用只读而不是禁用属性,所有值都成功发送到控制器。

答案 3 :(得分:0)

我遇到了同样的问题,但是一旦我为外键创建了一个HIDDEN FIELD ......一切都运行得很好......

表格示例:

@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 ...
}

PRETTY PICTURES:
enter image description here