MVC编辑器用于一个页面上多个编辑表单的模型绑定
本文关键字:编辑 表单 绑定 模型 用于 编辑器 一个 MVC | 更新日期: 2023-09-27 18:22:16
我有一个名为CategoryModel
的类,它的属性之一是相同类型的对象列表。所以CCD_ 2是CCD_。
在类别索引页面上,我为每个类别显示一个编辑器,这样用户就可以更改任何类别名称,而无需转到专用页面
<ul id="categories>
@Html.EditorFor(model => model.Categories)
</ul>
CategoryModel
的编辑器模板如下所示:
<li class="folder">
@using (Html.BeginForm("Edit", "Category", new { id = Model.Key }, FormMethod.Post, new { @class = "ajaxoff"})) {
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.Key)
@Html.HiddenFor(model => model.ParentKey)
@Html.HiddenFor(model => model.Sequence)
@Html.HiddenFor(model => model.IncludeDeleted)
@Html.TextBoxFor(model => model.Name, null, new { @class = "catName" })
@Html.ValidationMessageFor(model => model.Name)
<input type="submit" value="Save" class="icon save" />
}
</li>
我遇到的问题是提交表单没有正确绑定到CategoryController
:的Edit
操作
[HttpPost]
public ActionResult Edit(CategoryModel category)
{
// At this point all properties in category are null
}
如果我检查隐藏字段和文本框上的名称,它们将根据它们在当前类别中的位置进行标记(例如Categories[0].Name
)。然而,如果我创建了一个专用的编辑视图,它们只是根据字段名称命名(例如Name
)。
我已经尝试更改控制器以接受类别列表:
[HttpPost]
public ActionResult Edit(List<CategoryModel> categories)
{
var category = categories.First();
}
如果我提交了第一个类别,但没有提交其他类别(在这种情况下,Categories
为空),这是有效的。
我也尝试过改变我显示EditorFor的方式,通过这样做:
<ul id="categories>
@foreach (var cat in Model.Categories)
{
@Html.EditorFor(model => cat);
}
</ul>
它将每个类别的字段名称更改为相同(例如,所有类别名称都称为cat.Name
),我认为这是朝着正确方向迈出的一步。
那么,我如何正确绑定到我的控制器呢?我意识到我可以提交整个父类别,然后保存每个子类别,但这似乎是一种提交单个更改的低效方式。
我发现了如何做到这一点。Html.EditorFor
有一个重载,允许您指定htmlFieldName
属性(下面示例中的第三个参数):
@foreach (var cat in Model.Categories)
{
@Html.EditorFor(model => cat, null, "");
}
这将呈现所有没有任何前缀的字段名称,并允许我成功提交任何单个类别。
您的编辑操作接受CategoryModel类别,因此您需要重置模型前缀以进行右绑定。为此,您需要为HtmlHelper创建自己的扩展方法,如下所示:
public class BeginHtmlScope : IDisposable
{
private readonly TemplateInfo templateInfo;
private readonly string previousHtmlFieldPrefix;
public BeginHtmlScope(TemplateInfo templateInfo, string htmlFieldPrefix)
{
this.templateInfo = templateInfo;
previousHtmlFieldPrefix = templateInfo.HtmlFieldPrefix;
templateInfo.HtmlFieldPrefix = htmlFieldPrefix;
}
public void Dispose()
{
templateInfo.HtmlFieldPrefix = previousHtmlFieldPrefix;
}
}
public static class MyHtmlExtensions
{
public static IDisposable BeginHtmlScope(this HtmlHelper html, string htmlFieldPrefix)
{
return new BeginHtmlScope(html.ViewData.TemplateInfo, htmlFieldPrefix);
}
}
然后在编辑器模板中使用它:
@using (Html.BeginHtmlScope(""))
{
<li class="folder">
@using (Html.BeginForm("Edit", "Category", new { id = Model.Key }, FormMethod.Post, new { @class = "ajaxoff"})) {
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.Key)
@Html.HiddenFor(model => model.ParentKey)
@Html.HiddenFor(model => model.Sequence)
@Html.HiddenFor(model => model.IncludeDeleted)
@Html.TextBoxFor(model => model.Name, null, new { @class = "catName" })
@Html.ValidationMessageFor(model => model.Name)
<input type="submit" value="Save" class="icon save" />
}
</li>
}