2017-05-02 159 views
3

目標:要注入IHttpContextAccessor作爲依賴,autmapper輪廓的構造依賴注入到.NET的核心automapper資料 - IHttpContextAccessor返回null

爲什麼:我需要在當前用戶傳遞的的標識名稱爲建設我的域名之一的部分物品

問題 所獲得的用戶身份始終是空

到目前爲止我有什麼?

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 
     } 

是有什麼缺失?請指點?

回答

1

問題是AutoMapper配置通常是單身。它應該是單身人士,因爲構建它非常重。但請求中的用戶名不是單身作用域。您很可能必須找到不同的解決方案,而不是使用AutoMapper。

一個選擇,雖然我的:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 

IServiceProvider provider = services.BuildServiceProvider(); 

var mapperConfiguration = new MapperConfiguration(mc => 
{ 
    mc.AddProfile(new DtoToOtherProfile(provider.GetRequiredService<IHttpContextAccessor>())); 
}); 

這將構建服務供應商,並獲取從容器上下文訪問。 但是,這並沒有奏效。

+0

謝謝。我也試過這個,但真正的問題是User.Identity.Name從訪問中獲取 - 或者始終爲空 - 僅在調用控制器方法時才實例化,而不是在映射器配置文件級別實例化。所以想知道如果我做錯了或是預期的。 – Jaya

+0

@Jaya你有沒有找到任何解決方案。我掙扎了2天 –

+0

@GeorgePapadakis有一個基本問題,您依賴於來自單例作用域服務(AutoMapper映射器*應該是*,不要求它的請求範圍)的請求範圍內的事情。您很可能無法將請求用戶的用戶名映射到那裏。 – juunas

2

我相信這樣做的正確方法是不注入在ProfileIHttpContextAccessor而是創建一個單獨的IValueResolver並注入那裏IHttpContextAccessor。因此,只要做到以下幾點,在那裏我想要得到的HttpContext用戶要求

在你StartUp.csConfigureServices添加

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); 
    } 
    } 

這是驚人的工作!

+0

很酷。讓我試試這個並回復你。先謝謝你!! – Jaya

+0

雖然第二次認爲這更像是我直接在控制器上注入'IHttpContextAccessor',並簡單地使用該值來設置映射對象的屬性,因此不會通過映射器 – Jaya