如何在MVC的create视图中正确绑定list <object>

时间:2016-09-08 18:42:11

标签: c# asp.net-mvc asp.net-mvc-5

我遇到类似于下面假设的问题。我已经多次向另一个视图添加了部分视图,但我不确定如何让它们正确绑定到视图模型等。此外,如果单个fooName错误,则验证似乎会触发每个fooName。我已经将索引添加到了viewbag中,但我还不确定如何使用它。

注意:使用MVC5.2

查看模型

public class Thing
{
    public String thingName { get; set; }
    public List<Foo> Foos { get; set; }
}
public class Foo
{
    public String fooName { get; set; }
}

Foo View

@model Project.Models.Foo

<div class="form-horizontal">
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

    <div class="form-group">
        <div class="col-md-12">
            @Html.LabelFor(model => model.fooName, htmlAttributes: new { @class = "control-label" })
            @Html.EditorFor(model => model.fooName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.fooName, "", new { @class = "text-danger" })
        </div>
    </div>
</div>

Thing View

@model Project.Models.Thing
@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    <div class="form-horizontal">
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        <div class="form-group">
            <div class="col-md-12">
                @Html.LabelFor(model => model.thingName, htmlAttributes: new { @class = "control-label" })
                @Html.EditorFor(model => model.thingName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.thingName, "", new { @class = "text-danger" })
            </div>
        </div>
    </div>
    <div class="add-foo">
        @* at some point add more foos with ajax, for now k.i.s.s. *@
        @Html.Partial("/Views/Foo/Create.cshtml", new ViewDataDictionary { { "id", 1 } })
        @Html.Partial("/Views/Foo/Create.cshtml", new ViewDataDictionary { { "id", 2 } })
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
}

1 个答案:

答案 0 :(得分:1)

这里的问题是Foo部分渲染时没有更大模型的上下文。结果,您获得了一堆具有相同名称和ID的输入,即:

<input type="text" name="fooName" id="fooName" class="form-control">
...
<input type="text" name="fooName" id="fooName" class="form-control">
...

这就是为什么验证会触发所有这些因素,因为它们都是相同的。为了使部分行为正确,您需要将一些上下文传递给它。例如,如果您正在迭代可以执行的某些事情的现有实例:

@for (var i = 0; i < Model.Foos.Count; i++)
{
    @Html.Partial("_Foo", Model.Foos[i])
}

根据Model.Foos[i]位,Razor会生成正确的输入名称,如Foos[0].fooNameFoos[1].fooName等。

或者,您可以覆盖HtmlFieldPrefix

@Html.Partial("_Foo", foo1, new ViewDataDictionary { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "Foos[0]" } })
@Html.Partial("_Foo", foo2, new ViewDataDictionary { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "Foos[1]" } })
...

由于您计划通过JavaScript动态添加其他内容,因此您最好的选择是依靠Knockout或Angular等基于JavaScript数组为您渲染字段。然后,当您向该数组添加新的Foo实例时,该库将自动向具有索引名称属性的页面添加其他字段。