2014-05-22 3 views
3

50,000ft 개요 :웹 API의 요청 종속성 해결

IIS에서 호스팅하는 웹 API (OWIN).

OWIN 미들웨어에서 나는 요청을 인증하고 원칙을 만드는 등의 API 키 유효성 검사를 수행한다.

내 컨테이너로 Unity를 사용하고 있습니다. 컨트롤러에 실제로 도달하면 컨트롤러에서 내 리포지토리를 추상화하는 서비스 클래스를 주입합니다. 서비스 계층에서 감사 추적, 기록 로깅 등의 작업을 수행하므로 모든 서비스 클래스를 주입 할 수 있으므로 추가 혜택을 얻을 수 있습니다.

이 모든 작품, 인생은 좋은, yada yada yada.

까지

...

I API는 호출자가 특정 요청에 의해 수행되는 사용자 ID로 채우는 커스텀 헤더 값 (X-OnBehalfOf)를 갖는다. 이는 애플리케이션의 요구 사항이며 구현은 매우 간단합니다.

요청에 대한 액세스 권한이있는 곳 (OWIN 미들웨어, 컨트롤러 등)에서이 값을 쉽게 검색 할 수 있습니다. 그러나 해결해야 할 문제는 내 서비스 계층에서 그 가치를 얻으려고 할 때 발생합니다.

서비스 클래스의 인스턴스를 해결하기 위해 컨테이너를 사용하고 있기 때문에 최선의 해결책은 IHeaderProvider와 같은 것을 구현하고이를 서비스 클래스의 생성자에 삽입하는 것이지만 intitially 알아낼 수는 없습니다. 파이프 라인 외부에 있기 때문에 해당 클래스의 요청에 대한 참조를 얻는 방법.

확실한 방법이 있지만 문제가 계속 발생합니다. 누구든지 새로운 DI 컨테이너를 활용하여 저를 위해 작업을 수행 할 필요없이 참조를 얻는 방법을 알고 있습니까?

답변

4

종이에 적어 둘 필요가있는 것처럼 보입니다. 이것은 내가 그것을 해결하는 방법입니다

컨테이너 :

 container.RegisterType<IHeaderProvider, HeaderProvider>(new HierarchicalLifetimeManager()); 
     container.RegisterType<HttpContextBase>(new InjectionFactory(c => new HttpContextWrapper(HttpContext.Current))); 

IHeaderProvider :

public interface IHeaderProvider 
{ 
    Guid GetOnBehalfOf(); 
} 

HeaderProvider :

public class HeaderProvider : IHeaderProvider 
{ 
    private readonly HttpContextBase _httpContextBase; 

    public HeaderProvider(HttpContextBase httpContextBase) 
    { 
     _httpContextBase = httpContextBase; 
    } 

    public Guid GetOnBehalfOf() 
    { 
     var xOnBehalfOf = _httpContextBase.Request.Headers.Get("X-OnBehalfOfId"); 
     Guid userId; 

     if (string.IsNullOrWhiteSpace(xOnBehalfOf)) 
      throw new Exception("Missing user ID"); 

     if (Guid.TryParse(xOnBehalfOf, out userId)) 
     { 
      return userId; 
     } 

     throw new Exception("Invalid user ID"); 
    } 
} 
+0

이 좋은 솔루션입니다! 답으로 표시해야합니다. –

+0

고마워요! 나는 기분이 이상하기 때문에 종종 내 자신의 연구 결과를 답으로 표시하지 않습니다. :) 희망이 도움이되었습니다. –

+1

[HierarchicalLifetimeManager] (https://msdn.microsoft.com/en-us/library/ff660872(v=pandp.20) .aspx) 올바른 평생 옵션을 생각하지 않습니다. PerResolveLifetimeManager를 사용하는 것이 좋습니다. –