16

현재 HttpContext에서 현재 사용자 이름을 가져 와서 서비스 메서드에서 사용하는 작업으로 전달하는 ActionFilter가 있습니다. 예 :ASP.NET MVC : HTTPContext 및 Dependency Injection

Service.DoSomething(userName); 

이제는 작업 수준이 아니라 컨트롤러 생성자 수준에서이 작업을 수행해야하는 이유가 있습니다. 현재 컨트롤러를 생성하고 서비스를 주입하기 위해 구조체 맵을 사용하고 있습니다. 나는 다음과 같은 것을보고있다 :

public interface IUserProvider 
{ 
    string UserName { get; } 
} 

public class HttpContextUserProvider : IUserProvider 
{ 
    private HttpContext context; 

    public HttpContextUserProvider(HttpContext context) 
    { 
     this.context = context; 
    } 

    public string UserName 
    { 
     get 
     { 
      return context.User.Identity.Name; 
     } 
    } 
} 

나는 이것이 내가 사용 해본 첫 번째 프로젝트이기 때문에 나의 IoC foo는 정말 약하다.

그래서 내 질문은 ... HttpContextUserProvider에 대한 생성자에서 HttpContext를 전달할 구조체 맵을 어떻게 전달할 수 있습니까? 이것은 이상하게 보입니다 ... HttpContext에 대해 어떻게 생각하는지 모르겠습니다.

답변

8

인터페이스 추상 HttpContext.Current가 있습니다. 필요한 메서드 만 노출 GetUserName()은 HttpContext.Current.User.Identity.Name을 호출합니다. 구현을 예를 들어, 가능한 한 얇게 만드십시오.

추상화하여 다른 공급자 클래스에 삽입하면 http를 조롱하여 공급자를 테스트 할 수 있습니다. 문맥 추상화. 부수적 인 이점으로, 당신은 HockpContext 추상화로 다른 멋진 것들을 할 수 있습니다. 한 가지만 다시 사용하십시오. 가방 등에 제네릭 유형 매개 변수 추가

+0

"일반 유형 매개 변수를 가방에 추가 하시겠습니까?" 흥미로운 소리. –

+4

세션을 통해 강력한 형식의 랩퍼를 제공합니다 –

+3

샘플 코드/링크가 있습니까? 이것은 재미있을 것 같습니다. _ 이렇게 다소 이해할 수 없으므로 어떤 도움이나 조언도 받으실 수 있습니다 ... – Haroon

2

어쩌면 내가 떠난 것이지만 위의 대답은 나를 위해 작동하지 않습니다. (이후 삭제되었습니다 - 여전히 유용한 대답이었습니다 - SM이 생성자 인수를 전달하는 방법을 보여주었습니다). 대신 내가하는 경우 :

ObjectFactory.Initialize(x => 
{ 
    x.BuildInstancesOf<HttpContext>() 
     .TheDefault.Is.ConstructedBy(() => HttpContext.Current); 
    x.ForRequestedType<IUserProvider>() 
     .TheDefault.Is.OfConcreteType<HttpContextUserProvider>(); 
}); 

나는 그것을 얻는다. 내가 찾은 후 이런 짓을 : http://codebetter.com/blogs/jeremy.miller/archive/2008/03/20/if-you-need-something-in-structuremap-but-you-can-t-build-it-with-new.aspx


편집 : 브래드의 대답에

덕분에 내가있는 HttpContext에 더 나은 핸들을 생각 . 그의 대답은 분명히 작동하지만, 클래스 내에서 HttpContext.Current에 대한 호출을 좋아하는지 모르겠다. (의존성을 숨기는 것처럼 보이지만, 나는이 물건에 대한 전문가가 아니다.)

위의 코드는 내가 말할 수있는 한 HttpContext를 주입하기 위해 작동해야합니다. Matt Hinze는 HttpContext에서 필요한 모든 것이 User.Identity.Name 인 경우 그 점에 대해 명시 적으로 (HttpContext 주위에 Interface가 있어야만 내가 원하는 것을 노출 함) 추가해야한다는 점이 추가되었습니다. 나는 이것이 좋은 생각이라고 생각한다.

점심을 먹었을 때 나는 내 서비스가 정말로 문자열 : userName에 의존해야한다는 것을 깨달았다. IUserProvider에 의존하게되면 부가 가치가 없을 수도 있습니다. 그래서 나는 그것이 HttpContext에 의존하기를 원하지 않는다는 것을 알고, 필요한 모든 것이 문자열 (userName)이라는 것을 안다 - 나는이 연결을 만들기에 충분한 StructureMap foo를 배울 수 있는지 알아야한다. (sirrocoo의 대답은 어디에서 시작할 지에 대한 힌트를 주지만 그는 그것을 지웠다. *().

+0

생성자가 HttpContext의 종속성을 가질 때 IoC는 HttpContext.Current의 인스턴스를 전달합니다. 그리고 생성자가 IUserProvider의 종속성을 가질 때 IoC는 HttpContextUserProvider의 새 인스턴스를 인스턴스화하고이를 생성자로 전달합니다. –

+0

StructureMap 인터페이스가 잘 읽습니다. 내 혼란은 두 부분으로 생각됩니다 : 1) ForRequestedType을 사용한 적이 있습니다 - BuildInstancesOf를 대신 할 때를 어떻게 알 수 있습니까? (나는 단지이 간단한 문제 일 수 있습니다.) 2) 당연히 받아 들일 수 있습니까? 그 StructureMap은 HttpContext.Current를 얻는 방법을 알고 있습니까? 나는 HttpContext가 나를 혼란스럽게 만들 것이라고 생각한다. 나는 다른 모든 것이 더 명확한 근원을 가지고있는 것처럼 그것을 얻을 수있는 단일 소스를 생각할 수 없다. – anonymous

+0

실제로 내 솔루션이 작동하지 않았습니다. 하드 코어 오류가있는 경우에도 내부 예외가 JIT 제한 사항에 대해 말했습니다 ... wow – sirrocco

3

왜 당신이 귀찮게하는지 모르겠다. HttpContext.Current를 HttpContextUserProvider에서 직접 사용하는 것처럼 보인다. 다른 HttpContext로 대체하지 않을 것입니다 ...

+0

Yah ... 나는 * HttpContext를 얻지 못할 것이라고 생각합니다. HttpContext가 전역 적으로 존재하는 것으로 보이는 생성자를 통해 전달되는 것을 사용하는 데 익숙해 졌나요? – anonymous

+0

좋아, 반환 HttpContext.Current.User.Identity.Name; 작동합니다. 나는 여기에 다소 느린 것 같지만 현재 HttpContext를 찾는 방법을 아는 책임이있는 HttpContext의 정적 속성입니다. 유일한 단점은 정적 속성 또는 형식을 전달할 수 없기 때문에 생성자 삽입을 통해 HttpContext에 따라 명시 적으로 명시 할 수 없다는 것입니다 (적어도 생각하지 않음)? 당신은 HttpContext.Current를 반환하는 IHttpContextProvider와 같은 래퍼를 만들 수 있습니다. 그러면 HttpContext에 의존하는 무언가를 알 수 있습니까? 또는 바보입니다. – anonymous

+0

HttpContext를 웹을 참조하지 않는 서비스 계층에 어떻게 삽입 할 것인가? 어쩌면 우리는 레코드/데이터 집합이 현재 사용자에 따라 달라지는 경우에 대한 유스 케이스 시나리오라고 말할 수 있을까요? (asp.net mvc2) ... – Haroon

9

HttpContextUserProvider 대신 HttpContextBase을 사용해야하는 것처럼 들립니다.이것은 HttpContext의 모범적 인 추상화이며 모의 작성, UnitTest 작성 및 종속성 삽입을 가능하게합니다.

public class SomethingWithDependenciesOnContext 
{ 
    public SomethingWithDependenciesOnContext(HttpContextBase context) { 
     ... 
    } 

    public string UserName 
    { 
     get {return context.User.Identity.Name;} 
    } 
} 

ObjectFactory.Initialize(x => 
      x.For<HttpContextBase>() 
      .HybridHttpOrThreadLocalScoped() 
      .Use(() => new HttpContextWrapper(HttpContext.Current)); 
관련 문제