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

我有一个模型对象结构,其中包含一个带有字符串值的BarFoo类。

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

以及使用这种结构的视图模型

 public class HomeModel { public Foo Foo; } 

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

  
@using (Html.BeginForm("Save", "Home", FormMethod.Post)) {
@Html.TextBoxFor(m => m.Foo.Bar.Value)
}

在html中成为。

 

最后控制器像这样处理邮政厕所

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

我的问题是,一旦它击中了Save控制器动作, Foo中的Bar就为nullFoo已创建,但带有一个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) 

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

我刚刚发现了这种情况可能发生的另一个原因,即如果您的属性名为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 (等),它会突然再次运行。

我遇到了同样的问题,在我遵循@Stephen Muecke步骤之后,我意识到问题是由于我的输入被禁用(我在文档就绪时使用JQuery禁用它们)引起的,你可以在这里看到: 我如何提交禁用输入ASP.NET MVC? 。 最后,我使用只读而不是禁用属性,所有值都成功发送到控制器。

我遇到了同样的问题,但是一旦我为外键创建了一个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 ... } 

漂亮的图片:
在此处输入图像描述