我有一个复杂的视图模型,其中包含使用编辑器和显示模板递归渲染的其他对象的集合。
集合中的每个项目都包含一个表单模型,我想将其提交给控制器。请注意,我不想再将整个视图模型发回,只需要表单模型。
我的问题是MVC将每个对象呈现为集合的一部分,我不知道如何将集合中的单个对象绑定到控制器签名中的对象。
我知道我可以使用IEnumerable<Account>
再次绑定整个批次,但我正在尝试创建行级别提交而不是整个页面。
如果有人能指出我正确的方向,或者告诉我应该如何在MVC世界中做到这一点(我来自网络表格,所以有点被宠坏了)我会非常感激。
我在下面添加了一个示例HTML片段,还有我要发布的控制器。
<form action="/Home/Index" method="post">
<input id="Accounts_0__AccountName" name="Accounts[0].AccountName" type="text" value="Account 1" />
<input id="Accounts_0__AccountId" name="Accounts[0].AccountId" type="hidden" value="dddf5ca7-f8de-4192-b63a-3548f891e293" />
<input type="submit" value="Submit" />
</form>
<form action="/Home/Index" method="post">
<input name="Accounts[1].AccountName" type="text" value="Account 2" />
<input id="Accounts_1__AccountId" name="Accounts[1].AccountId" type="hidden" value="95d75f76-16ef-4cf2-b1e7-5fad782002c5" />
<input type="submit" value="Submit" />
</form>
[HttpPost]
public ActionResult Index(Account accounts)
{
...
}
答案 0 :(得分:4)
您可以尝试在编辑器模板中设置前缀:
@model AppName.Models.Account
@{
ViewData.TemplateInfo.HtmlFieldPrefix = string.Empty;
}
@using (Html.BeginForm("Index", "Home"))
{
@Html.TextBoxFor(x => x.AccountName)
@Html.HiddenFor(x => x.AccountId)
<input type="submit" value="Submit" />
}
如果我没有弄错,应该生成:
<form action="/Home/Index" method="post">
<input id="AccountName" name="AccountName" type="text" value="Account 1" />
<input id="AccountId" name="AccountId" type="hidden" value="dddf5ca7-f8de-4192-b63a-3548f891e293" />
<input type="submit" value="Submit" />
</form>
显然你意识到通过这样做你最终会得到无效的HTML(你将拥有多个具有相同id
的元素)。可能的解决方法是手动设置id:
@Html.TextBoxFor(x => x.AccountName, new { id = "some unique value like a GUID" })
@Html.HiddenFor(x => x.AccountId, new { id = "some unique value like a GUID" })
另一种可能性是为Account类型编写一个自定义模型绑定器,它会在绑定时忽略前缀。
答案 1 :(得分:0)
我通过向包含帐户前缀的编辑器模板添加隐藏字段并创建自定义模型绑定器来解决问题,该绑定器使用隐藏字段的值作为模型的名称。然后,默认绑定器可以绑定它,就像它是单个表单视图而不是视图模型集合一样。
@model MvcApplication1.Models.Account
@using (Html.BeginForm("Submit", "Home"))
{
@Html.TextBoxFor(m => m.AccountName)
@Html.HiddenFor(m => m.AccountId)
@Html.ValidationMessageFor(m => m.AccountName)
<input type="hidden" value="@ViewData.TemplateInfo.HtmlFieldPrefix" name="account.prefix" />
<input type="submit" value="Submit" />
}
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
bindingContext.ModelName = controllerContext.HttpContext.Request.Form["account.prefix"];
return base.BindModel(controllerContext, bindingContext);
}