复杂类型的模型绑定
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。
我制作了一个测试控制器和视图来测试复杂的绑定,但我似乎无法让它工作。
这是我的视图模型:
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。