_Layout页面中的.NET Core 3.1剃刀模型

时间:2020-10-22 00:01:06

标签: .net asp.net-core razor razor-pages asp.net-core-3.1

我有一个用户模型,其中包含登录名,名称,权限,联系信息等。

我想在_Layout页面的菜单栏中显示用户名,以便在每个页面上显示该用户名。我可以在_Layout页面上显示这样登录的用户...

@User.Identity.Name.Replace(@"MYDOMAIN\", "")

但是我想从模型中提取用户的真实姓名,并获得他们的权限来管理他们可以在公司Intranet网站上看​​到的内容。

问题是,如果我尝试在_Layout页面中设置页面模型,则该站点会崩溃,因为_Layout中的@RenderBody会加载引用其自身模型的其他页面。

也许我看错了,但是您又如何在不进入每次访问新页面的情况下使每个页面都访问数据库的情况下维护站点的用户名和权限呢?

另一种查看方式... 假设您的菜单是数据驱动的,并且该菜单存在于_Layout页面中。你怎么做到的?

谢谢。

1 个答案:

答案 0 :(得分:1)

首先,没有办法每次都不打数据库(至少是推荐的方法),因为您获取的用户数据和权限可能会发生变化。

第二,您可以在布局中进行@inject并通过ClaimsPrincipal User获取用户数据,因此可以这样操作: @inject UserManager<TheUser> userManager

然后您可以执行以下操作:var user=await userManager.FindByNameAsync(User.Identity.Name),现在您将用用户数据填充标签。

类似这样的东西:

_Layout.cshtml

@inject UserManager<TheUser> userManager
@{
   var user=await userManager.FindByNameAsync(User.Identity.Name)
} 

<div>
  @user.FullName
</div>

另一种方法是创建自定义的“声明原则”工厂。像这样的东西:

public class MyUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser> 
{     
    public MyUserClaimsPrincipalFactory(
        UserManager<ApplicationUser> userManager,
        IOptions<IdentityOptions> optionsAccessor)
            : base(userManager, optionsAccessor)     
    {
    }
      
    protected override async Task<ClaimsIdentity>GenerateClaimsAsync(ApplicationUser user)
    {
         var identity = await base.GenerateClaimsAsync(user);
         identity.AddClaim(new Claim("FullName", user.FullName));         
         return identity;     
    } 
}

然后将其添加到ConfigureServices

services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddClaimsPrincipalFactory<MyUserClaimsPrincipalFactory>(); 

现在您可以像这样访问它

User.FindFirst("FullName").Value

ClaimsPrincipal User还有一个User.IsInRole用于检查用户角色。

假设菜单是数据驱动的,并且该菜单位于_Layout页面中。你怎么做到的?

通常只将数据缓存在服务器内存中,这样就可以最大程度地减少数据库请求的数量(修改“数据”后清除缓存并进行重新缓存),但我建议您不要这样做用户数据。