你的主要问题很简单UserManager
没有包含相关实体的功能,例如您的UserProfile
。因此,您有两种选择:
-
直接使用您的上下文。然后你就可以急切地加载你的UserProfile
随着ApplicationUser
例如,只需对数据库进行一次查询:
var user = await _context.Users.Include(x => x.UserProfile).SingleOrDefaultAsync(x => x.UserName == model.UserName);
-
您可以显式加载相关的UserProfile
反而。不过,这将导致额外的查询,总共有两个查询:一个用于获取用户,另一个用于获取相关的个人资料:
await _context.Entry(user).Reference(x => x.UserProfile).LoadAsync();
然而,坦率地说,你不应该UserProfile
根本不。 ASP.NET Identity 与 ASP.NET Membership 不同。对于后者,你必须有一个单独的UserProfile
因为Membership中的“用户”是不可扩展的。在身份中,用户is可扩展,因此如果您需要其他配置文件信息,只需将其添加到类中即可:
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; } // FirstName
public string LastName { get; set; } // LastName
}
请注意,我在这里也删除了很多内容。重写没有意义Id
然后让它自动实现。此外,您显然不需要UserName
财产来自UserProfile
因为IdentityUser
已经有了,这当然意味着你的ApplicationUser
也有。
UPDATE
用户数据的持久化方式并不一定会影响它是否可以作为声明。换句话说,您不必将数据真正保存为声明才能将其作为声明访问。只是派生自UserClaimsPrincipalFactory<TUser>
, 覆盖CreateAsync
,然后将其注册到范围内的服务集合中。
public class MyClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser>
{
public MyClaimsPrincipalFactory(UserManager<TUser> userManager, IOptions<IdentityOptions> optionsAccessor)
: base(userManager, optionsAccessor)
{
}
public async override Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
{
var principal = await base.CreateAsync(user);
((ClaimsIdentity)principal.Identity).AddClaims(new[]
{
new Claim(ClaimTypes.GivenName, user.FirstName),
new Claim(ClaimTypes.Surname, user.LastName),
// etc.
});
return principal;
}
}
Then in ConfigureServices
:
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, MyClaimsPrincipalFactory>();