如何处理集合中每一行重复相同形式的MVC模型绑定前缀?

Osk*_*ren 3 asp.net-mvc model-binding asp.net-mvc-3

我的主视图模型有一个ChildViewModel的集合.在视图中,我遍历集合并调用EditorFor(),如下所示:

@for (int i = 0; i < Model.Children.Count; i++)
{
    @Html.EditorFor(m => m.Child[i]);
}
Run Code Online (Sandbox Code Playgroud)

编辑器模板如下所示:

@model ChildModel

@using (Html.BeginForm("EditChild", "MyController"))
{
    @Html.HiddenFor(m => m.ChildId)
    @Html.TextBoxFor(m => m.ChildName)
}
Run Code Online (Sandbox Code Playgroud)

这将生成标记,其中每个子项都是单独的形式,并且每个这样的表单将具有名为Child [0] .ChildName的输入控件.我为每个孩子使用单独的表单,因为孩子们将在每行显示一个,然后用户可以编辑并提交单行.

我的表单操作方法是:

[HttpPost]
public ActionResult EditChild(ChildViewModel form) { }
Run Code Online (Sandbox Code Playgroud)

问题是,当调用它时,模型的所有属性都将为null,因为模型绑定器不知道前缀.在某些情况下,我们可以使用BindAttribute告诉模型绑定器有关前缀的信息,但在这种情况下,前缀不是常量:它将是Child [0],Child [1]等.

总之,我们希望为集合的每一行重复相同的表单,然后允许用户POST一个表单.在这种情况下,Web如何处理id,名称,前缀和模型绑定?

dre*_*619 5

我和你有同样的问题,有我的解决方案,希望它可以帮助你.

在EditorTemplate或Partial View中添加隐藏的输入

<input type="hidden" name="__prefix" value="@ViewData.TemplateInfo.HtmlFieldPrefix" />
Run Code Online (Sandbox Code Playgroud)

定义自定义模型绑定器并覆盖BindModel方法

public class CustomModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var prefixValue = bindingContext.ValueProvider.GetValue("__prefix");
        if (prefixValue != null)
        {
            var prefix = (String)prefixValue.ConvertTo(typeof(String));
            if (!String.IsNullOrEmpty(prefix) && !bindingContext.ModelName.StartsWith(prefix))
            {
                if (String.IsNullOrEmpty(bindingContext.ModelName))
                {
                    bindingContext.ModelName = prefix;
                }
                else
                {
                    bindingContext.ModelName = prefix + "." + bindingContext.ModelName;

                    // fall back
                    if (bindingContext.FallbackToEmptyPrefix && 
                        !bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
                    {
                        bindingContext.ModelName = prefix;
                    }
                }
            }
        }
        return base.BindModel(controllerContext, bindingContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

模型绑定器将修剪前缀并使默认模型绑定起作用.