目标:将IHttpContextAccessor
作为依赖项注入自动映射器配置文件的构造函数
为什么:我需要传递当前用户的身份名称作为构建我的某个域对象的一部分
问题 获取的用户标识始终为空
到目前为止我有什么?
Startup.cs
mc.AddProfile(new DtoToOtherProfile(new HttpContextAccessor()));
//OR
var mapperConfiguration = new MapperConfiguration(mc =>
{
IServiceProvider provider = services.BuildServiceProvider();
mc.AddProfile(new DtoToOtherProfile(provider.GetService<IHttpContextAccessor>()));
});
DtoToOtherProfile.cs
public DtoToOtherProfile(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
CreateMap<MyDto, MyOther>()
.ConstructUsing(myDto => new myOther(myDto.prop1, myDto .prop2, _httpContextAccessor.HttpContext.User.Identity.Name)); // the name is what i intend to pass
// other mapping
}
Controller.cs
public async Task<IActionResult> Create([FromBody]MyDto model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// save campaign
var myOtherModel = _mapper.Map<MyOther>(model);
// myOtherModel.UserName is always null
// rest
}
有什么遗失的吗?指针好吗?
答案 0 :(得分:6)
我认为正确的方法不是在IHttpContextAccessor
中注入Profile
,而是创建一个单独的IValueResolver
并注入IHttpContextAccessor
。所以,只需执行以下操作,我想获得httpcontext的用户声明
在StartUp.cs
内ConfigureServices
添加
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddAutoMapper();
使用您的映射创建配置文件
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<QueryUniqueDto, QueryUnique>()
.ForMember(s=>s.UserClaim,opt=>opt.ResolveUsing<IdentityResolver>());
}
}
创建IValueResolver
public class IdentityResolver : IValueResolver<QueryUniqueDto, QueryUnique, UserClaim>
{
private IHttpContextAccessor _httpContextAccessor;
public IdentityResolver(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public UserClaim Resolve(QueryUniqueDto source, QueryUnique destination, UserClaim destMember, ResolutionContext context)
{
return Helper.GetClaimsFromUser(_httpContextAccessor.HttpContext?.User.Identity as ClaimsIdentity);
}
}
那工作真棒!!!
答案 1 :(得分:1)
问题是AutoMapper配置通常是单例。它应该是单身,因为构建它是相当沉重的。但请求中的用户名不是单例范围。您很可能必须找到不同的解决方案,而不是使用AutoMapper。
我的一个选择是:
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
IServiceProvider provider = services.BuildServiceProvider();
var mapperConfiguration = new MapperConfiguration(mc =>
{
mc.AddProfile(new DtoToOtherProfile(provider.GetRequiredService<IHttpContextAccessor>()));
});
这将构建服务提供者并从容器中获取上下文访问者。 但是,这不起作用。