我有一个基本的问题,关于如何站立一个新的UserManager实例(或在请求堆栈中我需要它的地方访问它),然后如何使用它来获取包含自定义外部的IdentityUser实例密钥对象(即,在IdentityUser已作为自定义ApplicationUser扩展的情况下)。例如,我有:
public class ApplicationUser : IdentityUser<Guid>
{
public ApplicationUser() : base(){ }
public int? PersonId { get; set; }
public Person Person { get; set; } = new Person();
}
作为POCO实体的人,其中包含一些我不想直接放入IdentityUser类型的项目。
在我的网络项目Startup.cs
中,我注册了自定义声明转换,如下所示:
services.AddSingleton<IClaimsTransformation, ClaimsTransformation>();
在我的ClaimsTransformation类中,我正在进行这样的转换操作:
public class ClaimsTransformation : IClaimsTransformation
{
public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
if (
principal != null
& (!principal.HasClaim(c => c.Type == CustomClaimType.DisplayName)
&& (principal.HasClaim(c => c.Type == ClaimTypes.Email) || principal.HasClaim(c => c.Type == ClaimTypes.NameIdentifier)))
)
{
ClaimsIdentity identity = (ClaimsIdentity)principal.Identity;
if (identity != null && identity.IsAuthenticated)
{
CoreUserService userService = new CoreUserService();
ApplicationUser applicationUser = await userService.FetchAsync(identity);
if (applicationUser != null)
{
Claim claimDisplayName = CustomClaim.Create(CustomClaimType.DisplayName, applicationUser.Person.Name.DisplayName);
if (claimDisplayName != null)
{
identity.AddClaim(claimDisplayName);
}
}
}
}
return await Task.FromResult(principal);
}
}
这确实有效。你无法看到发生在幕后的所有事情,但最重要的是我要通过直接解决我的DAL DbContext来获取相关的Person实体。这似乎是不卫生的。我当然更喜欢让UserManager这样做。我不喜欢混合和匹配工作模式。如果我要使用AspIdentity那么这就是我想要为所有身份管理所坚持的。
我不确定的是请求堆栈中我的TransformAsync方法被调用的位置,以及我是否可以将UserManager传入其中,或者是否可以使用它。我尝试在方法的上下文中解雇一个,但是 - 我的天意 - 它有一大堆的开销!如果我不是必须的话,我不会站起来这么昂贵的物品。
但即使我有一个UserManager的句柄,我老实说也不知道如何让它返回一个包含我相关的Person对象的ApplicationUser。我不知道为什么我也无法想出这个。看起来应该很简单,但事实并非如此。