ASP.NET视图中如何访问嵌套实体GrandChildren属性生成表头与输入控件?
解决多层级实体的显示与绑定问题
一、生成GrandChildren属性的表头(DisplayNameFor)
直接用model => model.childs.kids.name会报错,因为childs是集合类型(ICollection<Children?>),集合本身没有kids属性;同理kids也是集合,没有name属性。可以通过以下两种方式解决:
方式1:利用集合元素表达式获取DisplayName
通过FirstOrDefault()定位到集合中的单个元素(仅用于构建表达式树,不会实际执行查询),再访问其属性:
<thead> <tr> <th>@Html.DisplayNameFor(model => model.childs.FirstOrDefault()?.kids.FirstOrDefault()?.id)</th> <th>@Html.DisplayNameFor(model => model.childs.FirstOrDefault()?.kids.FirstOrDefault()?.name)</th> </tr> </thead>
方式2:直接针对GrandChildren类获取DisplayName
不依赖集合对象,直接通过类的实例获取属性显示名:
<thead> <tr> <th>@Html.DisplayNameFor(_ => new GrandChildren().id)</th> <th>@Html.DisplayNameFor(_ => new GrandChildren().name)</th> </tr> </thead>
二、使用输入控件绑定GrandChildren属性(asp-for)
多层级集合需要通过索引遍历生成带正确命名的输入控件,才能让ASP.NET Core模型绑定器识别并绑定到对应元素。
步骤1:修正命名一致性
你的实体类中Parent的属性是childs,但View里写的是Model.Children,这会导致编译错误,建议统一命名(符合C#大驼峰规范):
public class Parent { public int id {get; set;} // 修正属性名为Children public ICollection<Children?>? Children {get; set;} }
步骤2:嵌套遍历生成输入控件
使用for循环(需要索引)遍历每层集合,生成带索引的asp-for表达式:
@model Parent @if (Model.Children != null) { @for (int i = 0; i < Model.Children.Count; i++) { <h5>第@(i+1)个孩子的后代</h5> @if (Model.Children[i].kids != null && Model.Children[i].kids.Any()) { @for (int j = 0; j < Model.Children[i].kids.Count; j++) { <div class="form-group"> <label>@Html.DisplayNameFor(m => m.Children[i].kids[j].id)</label> <input asp-for="Children[i].kids[j].id" class="form-control" /> </div> <div class="form-group"> <label>@Html.DisplayNameFor(m => m.Children[i].kids[j].name)</label> <input asp-for="Children[i].kids[j].name" class="form-control" /> </div> } } } }
额外注意点
- 可以用数据注解自定义属性显示名,比如给GrandChildren的属性加
[Display(Name = "后代ID")] - 建议在实体类构造函数中初始化集合,避免空引用异常:
public Parent() => Children = new List<Children?>(); public Children() => kids = new List<GrandChildren>();
内容的提问来源于stack exchange,提问作者SuperNev
相关产品推荐
相关产品推荐

