[英]Complex object and model binder ASP.NET MVC
我有一个带有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>
最后,控制器来处理这样的帖子
[HttpPost]
public ActionResult Save(Foo foo)
{
// Magic happends here
return RedirectToAction("Index");
}
我的问题是,一旦Foo
中的Bar
命中了Save
控制器动作(创建Foo
但Bar
字段为null
,它就为null
。
我认为MVC中的模型绑定程序将能够创建Foo
和Bar
对象并设置Value
属性,只要它看起来像上面一样即可。 我想念什么?
我也知道我的视图模型有点复杂,可能会更简单,但是对于我想做的事情,如果我可以使用更深的对象结构,那将对我有很大帮助。 上面的示例使用ASP.NET 5。
首先, DefaultModelBinder
不会绑定到字段,因此您需要使用属性
public class HomeModel
{
public Foo Foo { get; set; }
}
其次,助手正在基于HomeModel
生成控件,但是您将其发回到Foo
。 将POST方法更改为
[HttpPost]
public ActionResult Save(HomeModel model)
或使用BindAttribute
指定Prefix
(实际上是从发布的值中Bar.Value
前缀的值-出于绑定的目的, Foo.Bar.Value
变为Bar.Value
)。
[HttpPost]
public ActionResult Save([Bind(Prefix="Foo")]Foo model)
还要注意,您不应使用与属性之一相同的名称来命名方法参数,否则绑定将失败并且模型将为null。
我刚刚发现了发生这种情况的另一个原因,那就是如果您的媒体资源名为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
属性,它将无法绑定(不仅在发布时,甚至在生成表单时)。 如果将Settings
重命名为Settings
DSettings
(等),则突然可以再次使用。
我遇到了同样的问题,按照@Stephen Muecke的步骤进行操作后,我意识到问题是由我的输入被禁用(我在准备好文档的JQuery上禁用它们)引起的,您可以在此处看到: 如何在以下位置提交禁用的输入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 ...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.