目前有ApplicationUser
类包含一些自定义属性,例如:
public class ApplicationUser : IdentityUser
{
public string Name { get; set; }
public List<Content> Content { get; set; }
}
我想让当前记录的用户获得相关数据列表(Content
属性)。
在我的控制器中,如果我把:
Applicationuser user = await _userManager.GetUserAsync(HttpContext.User);
我获取了已登录的用户,但没有任何相关数据。
但是,如果我使用ApplicationDbContext
检索当前用户,如下所示,我可以检索相关数据:
ApplicationUser user = await _userManager.GetUserAsync(HttpContext.User);
ApplicationUser userWithContent = _context.Users.Include(c => c.Content).Where(u => u.Id == user.Id).ToList();
但这对我来说似乎不正确!
有什么想法吗?
答案 0 :(得分:0)
检查[UserManager][1]
的源代码,GetUserAsync将最终调用FindByIdAsync
,这将由IUserStore
实现提供。查看问题中的源代码,很有可能使用EFCore作为IUserStore实现。
在使用EFCore的情况下,提到here不能将Find
与include
结合使用,所以我请您做好准备,急切地加载问题,实际上正确。
答案 1 :(得分:0)
如果每个请求中都需要这些属性,则有一种更好的方式来获取它们,而无需在每个请求中查询数据库。
您可以通过编写自己的Claims
并从IUserClaimsPrincipalFactory<TUser>
中读取它们来将这些属性存储为HttpContext.User
public class CustomUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser>
{
public CustomUserClaimsPrincipalFactory(UserManager<ApplicationUser> userManager, IOptions<IdentityOptions> optionsAccessor)
: base(userManager, optionsAccessor)
{
}
protected async override Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
{
ClaimsIdentity identity = await base.GenerateClaimsAsync(user);
identity.AddClaim(new Claim("Name", user.Name));
for (int i = 0; i < user.Content.Count; i++)
{
string content = Newtonsoft.Json.JsonConvert.SerializeObject(user.Content[i]);
identity.AddClaim(new Claim("Content", content));
}
return identity;
}
}
还需要将其注册到服务集合
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, CustomUserClaimsPrincipalFactory>();
您可以使用此代码访问这些属性
string name = httpContext.User.FindFirstValue("Name");
List<Content> contents = new List<Content>();
foreach (Claim claim in httpContext.User.FindAll("Content"))
{
Content content = Newtonsoft.Json.JsonConvert.DeserializeObject<Content>(claim.Value);
contents.Add(content);
};