如何在ASP.NET Identity视图中显示自定义字段DisplayName
解决方法
你无法直接通过User.Identity.DisplayName访问自定义字段,是因为User.Identity对应的ClaimsIdentity默认不会包含你新增的DisplayName属性。下面提供两种可行的实现方式:
方法一:直接通过UserManager获取用户实例
利用你已经注入的UserManager<AppUser>,在视图中异步获取当前登录用户的完整实例,直接读取DisplayName字段:
@inject SignInManager<AppUser> SignInManager @inject UserManager<AppUser> UserManager <ul class="navbar-nav"> @if (SignInManager.IsSignedIn(User)) { var currentUser = await UserManager.GetUserAsync(User); <li class="nav-item"> <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage"> Hello @(currentUser?.DisplayName ?? currentUser?.UserName)! </a> </li> } <!-- 未登录状态的菜单逻辑 --> else { <li class="nav-item"> <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a> </li> } </ul>
说明:
UserManager.GetUserAsync(User)可以通过当前登录用户的ClaimsPrincipal直接获取对应的AppUser实例- 用
??做兜底处理,避免DisplayName为空时显示UserName
方法二:将DisplayName添加到登录Claims中(性能更优)
如果不想每次渲染视图都查询数据库,可以在用户登录时把DisplayName写入登录Claims,后续直接从Claims读取:
步骤1:自定义ClaimsPrincipal工厂
创建一个类负责生成包含自定义字段的Claims:
using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; using System.Security.Claims; using System.Threading.Tasks; namespace RacePull.Models { public class AppUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<AppUser> { public AppUserClaimsPrincipalFactory(UserManager<AppUser> userManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor) { } protected override async Task<ClaimsIdentity> GenerateClaimsAsync(AppUser user) { var identity = await base.GenerateClaimsAsync(user); // 把DisplayName添加到Claims中,为空时用UserName兜底 identity.AddClaim(new Claim("DisplayName", user.DisplayName ?? user.UserName)); return identity; } } }
步骤2:注册自定义工厂
在Program.cs中替换默认的ClaimsPrincipal工厂:
builder.Services.AddScoped<IUserClaimsPrincipalFactory<AppUser>, AppUserClaimsPrincipalFactory>();
步骤3:在视图中直接读取Claims
@inject SignInManager<AppUser> SignInManager <ul class="navbar-nav"> @if (SignInManager.IsSignedIn(User)) { var displayName = User.FindFirstValue("DisplayName"); <li class="nav-item"> <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage"> Hello @displayName! </a> </li> } <!-- 未登录状态菜单 --> </ul>
说明:这种方式只会在用户登录时查询一次数据库,后续渲染视图时直接从Cookie中的Claims读取,性能更高效。
内容的提问来源于stack exchange,提问作者Rockets24
相关产品推荐
相关产品推荐

