复杂类型的模型绑定

Model binding with complex type

我制作了一个测试控制器和视图来测试复杂的绑定,但我似乎无法让它工作。

这是我的视图模型:

public class TestViewModel
{
    public SubTest MainTest { get; set; }

    public List<SubTest> SubTestList { get; set; }
}

public class SubTest
{
    public string Name { get; set; }
    public int Id { get; set; }
}

这是我的看法:

@model TestViewModel    

@{
    using (Html.BeginForm())
    {
        <h2>Main</h2>

        <p>
            @Html.DisplayTextFor(m => m.MainTest.Id)
            =>
            @Html.DisplayTextFor(m => m.MainTest.Name)
        </p>

        <h2>Subs</h2>

        foreach (var sub in Model.SubTestList)
        {
            <p>
                @Html.DisplayTextFor(m => sub.Id)
                =>
                @Html.DisplayTextFor(m => sub.Name)
            </p>
        }

        <button type="submit">Submit</button>
    }
}

这是我的控制器:

public ActionResult Test()
{
    TestViewModel tvm = new TestViewModel();
    tvm.MainTest = new SubTest() { Id = 0, Name = "Main Test" };

    tvm.SubTestList = new List<SubTest>()
    {
        new SubTest() { Id = 1, Name = "Sub Test 1" } ,
        new SubTest() { Id = 2, Name = "Sub Test 2" } ,
        new SubTest() { Id = 3, Name = "Sub Test 3" } ,
        new SubTest() { Id = 4, Name = "Sub Test 4" } ,
    };

    return View(tvm);
}

[HttpPost]
public ActionResult Test(TestViewModel tvm)
{
    return View(tvm);
}

当我加载页面时,一切都显示正确,但是如果我在 POST 方法中设置断点,我看到参数值都是空的。

我做错了什么?

首先DisplayTextFor()不生成表单控件(input,textarea,select)因此没有任何表单可以post返回。

其次,如果您确实想编辑模型的值(比如使用文本框),那么您需要使用 for 循环(或自定义 EditorTemplate for typeof SubTest) 不是 collection 属性 的 foreach 循环,例如

for (int i = 0; i < Model.SubTestList.Count; i++)
{
  @Html.TextBoxFor(m => m.SubTestList[i].Id)
  @Html.TextBoxFor(m => m.SubTestList[i].Name)
}

或使用 EditorTemplate(模板名称必须与您的模型类型匹配

/View/Shared/EditorTemplates/SubTest.cshtml

@model yourAssembly.SubTest
@Html.TextBoxFor(m => m.Id)
@Html.TextBoxFor(m => m.Name)

并在主视图中

@model TestViewModel 
....
@Html.EditorFor(m => m.SubTestList)

EditorFor() 方法接受 IEnumerable<T> 并且足够聪明,可以从模板中为 collection 中的每个项目呈现 html。