如何在具有模型继承的 ASP.Net Core Razor 页面中使用 DisplayTemplates?
How to use DisplayTemplates in ASP.Net Core Razor Pages with Model Inheritance?
尝试在 ASP.Net Core 2.2 中获取 DisplayTemplates 以与从基础 class 继承的 classes 一起工作,类似于这个问题 How to handle an entity model with inheritance in a view?
Principal
DisplayTemplate 正在用于列表中的所有项目,我缺少什么?
PageModel
public class IndexModel : PageModel
{
public List<Principal> Principals { get; set; } = new List<Principal>();
public void OnGet()
{
Principals.Add(new Principal { Id = 1, Name = "Principal 1" });
Principals.Add(new UserPrincipal { Id = 1, Name = "User 1", Age = 30 });
Principals.Add(new GroupPrincipal { Id = 1, Name = "Group 1", Members = 5 });
Principals.Add(new UserPrincipal { Id = 1, Name = "User 2", Age = 40 });
Principals.Add(new GroupPrincipal { Id = 1, Name = "Group 2", Members = 3 });
}
}
public class Principal
{
public int Id { get; set; }
public string Name { get; set; }
}
public class UserPrincipal : Principal
{
public int Age { get; set; }
}
public class GroupPrincipal : Principal
{
public int Members { get; set; }
}
RazorPage
@page
@model IndexModel
@foreach(var principal in Model.Principals)
{
@Html.DisplayFor(p => principal)
}
~/Pages/Shared/DisplayTemplates/Principal.cshtml
@model Principal
<div>
<h4>Principal</h4>
@Model.Name
</div>
~/Pages/Shared/DisplayTemplates/UserPrincipal.cshtml
@model UserPrincipal
<div>
<h4>User</h4>
@Model.Name, Age @Model.Age
</div>
~/Pages/Shared/DisplayTemplates/GroupPrincipal.cshtml
@model GroupPrincipal
<div>
<h4>Group</h4>
@Model.Name, Members @Model.Members
</div>
原因
The Principal DisplayTemplate is being used for all items in the list,
那是因为@Html.DisplayFor(expression)
中的表达式根本不会被执行。它们被静态解析。
例如,如果我们有一个表达式 m.a.b.c
,其中 a
在运行时是 null
,那么 @Html.DisplayFor(m => m.a.b.c)
是仍然能够知道 c
.
的模板
由于您声明 Principals
类型为 List<Principal>
,即使您将 Model.Principals
保持 UserPrincipal
或 GroupPrincipal
在运行时 ,"parser" 仍将 principal
视为基础 Principal
类型:他们不检查 实例 的真实类型。他们只是静态解析类型。
如何修复
在调用 Html.DisplayFor()
时传递模板名称,以便 Html Helper 知道您要使用的真实模板:
@page
@model IndexModel
@foreach (var principal in Model.Principals)
{
@Html.DisplayFor(p => principal, principal.GetType().Name)
}
演示
尝试在 ASP.Net Core 2.2 中获取 DisplayTemplates 以与从基础 class 继承的 classes 一起工作,类似于这个问题 How to handle an entity model with inheritance in a view?
Principal
DisplayTemplate 正在用于列表中的所有项目,我缺少什么?
PageModel
public class IndexModel : PageModel
{
public List<Principal> Principals { get; set; } = new List<Principal>();
public void OnGet()
{
Principals.Add(new Principal { Id = 1, Name = "Principal 1" });
Principals.Add(new UserPrincipal { Id = 1, Name = "User 1", Age = 30 });
Principals.Add(new GroupPrincipal { Id = 1, Name = "Group 1", Members = 5 });
Principals.Add(new UserPrincipal { Id = 1, Name = "User 2", Age = 40 });
Principals.Add(new GroupPrincipal { Id = 1, Name = "Group 2", Members = 3 });
}
}
public class Principal
{
public int Id { get; set; }
public string Name { get; set; }
}
public class UserPrincipal : Principal
{
public int Age { get; set; }
}
public class GroupPrincipal : Principal
{
public int Members { get; set; }
}
RazorPage
@page
@model IndexModel
@foreach(var principal in Model.Principals)
{
@Html.DisplayFor(p => principal)
}
~/Pages/Shared/DisplayTemplates/Principal.cshtml
@model Principal
<div>
<h4>Principal</h4>
@Model.Name
</div>
~/Pages/Shared/DisplayTemplates/UserPrincipal.cshtml
@model UserPrincipal
<div>
<h4>User</h4>
@Model.Name, Age @Model.Age
</div>
~/Pages/Shared/DisplayTemplates/GroupPrincipal.cshtml
@model GroupPrincipal
<div>
<h4>Group</h4>
@Model.Name, Members @Model.Members
</div>
原因
The Principal DisplayTemplate is being used for all items in the list,
那是因为@Html.DisplayFor(expression)
中的表达式根本不会被执行。它们被静态解析。
例如,如果我们有一个表达式 m.a.b.c
,其中 a
在运行时是 null
,那么 @Html.DisplayFor(m => m.a.b.c)
是仍然能够知道 c
.
由于您声明 Principals
类型为 List<Principal>
,即使您将 Model.Principals
保持 UserPrincipal
或 GroupPrincipal
在运行时 ,"parser" 仍将 principal
视为基础 Principal
类型:他们不检查 实例 的真实类型。他们只是静态解析类型。
如何修复
在调用 Html.DisplayFor()
时传递模板名称,以便 Html Helper 知道您要使用的真实模板:
@page @model IndexModel @foreach (var principal in Model.Principals) { @Html.DisplayFor(p => principal, principal.GetType().Name) }