foreach 不会为您的输入生成正确的名称,因此在您提交时模型绑定器无法识别它。您可以使用 for 循环(提供正确的索引),但我建议您使用 EditorTemplates :
在您的主视图中:
@Html.EditorFor(model => model.Items)
假设您的Items 属性是ItemModel 的集合(将其替换为您正在使用的类型),您将创建一个EditorTemplate(必须位于Views/Shared/EditorTemplates 文件夹中),它采用@ 987654329@作为模型:
@model ItemModel
@Model.Info @Html.EditorFor(model => model.Id)
@Html.EditorFor(model => model.Parameters)
假设Parameters' 类型是ParameterModel 的集合(同样,使用您的真实类型),创建另一个EditorTemplate(仍然位于Views/Shared/EditorTemplates 文件夹中):
@model ParameterModel
@Model.Info @EditorFor(model => model.Value)
您的所有字段都将正确命名,允许模型绑定器在您提交表单时获取正确的值。
现在,对正在发生的事情进行更多解释:模板(DisplayTemplate 或 EditorTemplate,根据您的需要)提供特定模型的表示,该模型可在您的所有视图中重复使用,并在您使用时自动调用使用HtmlHelpers(它按照约定工作,模板名称必须是类型名称)。 ASP.NET MVC 已经有内置模板,适用于 string、DateTime 等类型(这就是为什么当您使用带有 boolean 属性的 @Html.Editor 或 @Html.EditorFor 时会得到一个复选框)。
当您将@Html.EditorFor 与IEnumerable<ItemModel> 一起使用时,它会检查名为ItemModel.cshtml 的EditorTemplate 是否存在,并使用它来显示您集合中的每个ItemModel。它正确生成输入字段,以便在您提交时取回值。在这个EditorTemplate 中,您显示了它的属性,包括Parameters,它也是一个复杂类型的集合。然后,它再次搜索名为ParameterModel.cshtml(在本例中)的EditorTemplate,并使用它来显示每个参数。
如果没有定义模板,它使用对象类型的默认模板,它只显示简单的属性(如string、int...)。
这个强大的功能有助于保持代码清晰,同时在构建视图时提供灵活性。请记住,这些模板具有特定的位置:Views/Shared/EditorTemplates(或Views/Shared/DisplayTemplates)或Views/{MyControllerName}/EditorTemplates(Views/{MyControllerName}/DisplayTemplates)。