2009-11-30 7 views
12

HTTP 컨텍스트와 같은 항목에 의존하는 여러 가지 종속성 삽입 서비스가 있습니다. 지금 나는 Application_Start 핸들러의 singletons Windsor 컨테이너로 구성하고 있습니다. 이는 분명히 이러한 서비스에 대한 문제입니다.ASP.NET MVC & Windsor.Castle : HttpContext 종속 서비스로 작업하기

이 문제를 해결하는 가장 좋은 방법은 무엇입니까? 나는 그들을 transient으로 만든 다음 각 HTTP 요청 후에 해제 할 것을 고려하고 있습니다. 하지만 HTTP 컨텍스트를 주입하는 가장 좋은 방법/장소는 무엇입니까? 컨트롤러 공장 또는 다른 곳?

답변

5

Castle Windsor를 사용하면 평생 PerWebRequest을 사용할 수 있습니다. 이는 요구 사항에 매우 잘 맞아야합니다.

즉, 서비스에 HTTP 항목을 삽입하면 컨테이너가 적절한 수명 관리를 처리합니다. 그러나 이러한 서비스 (및 해당 서비스의 모든 사용자 등)도 PerWebRequest (또는 Transient)로 등록해야합니다. 이러한 서비스를 싱글 톤으로 등록하면 오래된 컨텍스트를 유지하게됩니다.

+0

마크, 정보 주셔서 감사합니다 - PerWebRequest에 대해 몰랐습니다. 나는 그것을 조사 할 것이다. –

+0

Mark, PerWebRequest를 살펴 봤지만 서비스가 HttpContext를 얻는 방법을 아직 볼 수 없습니다. HttpContextBase의 인스턴스를 컨테이너에 직접 등록하려고하면 인스턴스가 이전 요청에 이미 등록되어 있으므로 두 번째 요청 후에 실패합니다. 지금까지 Google에서 아무 것도 찾을 수 없었습니다 ... –

+0

내가하려는 일을 오해했을 수도 있지만, Application_Start에서 HttpContext를 사용할 수 없습니다.이 시점에서 * HttpContext가 없습니다 (PerWebRequest 또는 PerWebRequest가 없음).). 이제 생각해 보면,이 수명은 이미 ASP.NET MVC 프레임 워크에서 관리되고 있으므로 DI 컨테이너에서 HttpContext의 수명을 제어하려고 시도하는 것은 의미가 없습니다.당신이 할 수있는 일은 커스텀 IControllerFactory에 연결하여 그 시점에서 제공되는 HttpContext를 잡은 다음 팩토리 메소드를 사용하여 그 밖의 모든 것을 연결하는 것입니다. –

24

Mark와 마찬가지로 이러한 http 의존 서비스를 PerWebRequest 또는 Transient로 등록해야합니다.

public class Service { 
    private readonly HttpRequestBase request; 

    public Service(HttpRequestBase request) { 
     this.request = request; 
    } 

    public string RawUrl { 
     get { 
      return request.RawUrl; 
     } 
    } 
} 

... 

protected void Application_Start(object sender, EventArgs e) { 
    IWindsorContainer container = new WindsorContainer(); 
    container.AddFacility<FactorySupportFacility>(); 
    container.AddComponentLifeStyle<Service>(LifestyleType.Transient); 

    container.Register(Component.For<HttpRequestBase>() 
     .LifeStyle.PerWebRequest 
     .UsingFactoryMethod(() => new HttpRequestWrapper(HttpContext.Current.Request))); 

    container.Register(Component.For<HttpContextBase>() 
     .LifeStyle.PerWebRequest 
     .UsingFactoryMethod(() => new HttpContextWrapper(HttpContext.Current))); 
} 

쉽게 테스트를 위해 그것을 밖으로 조롱 수 HttpRequestBase를 사용하는 대신 HttpRequest 기준 : 여기에 등록하고 HttpRequest에 또는 HttpContext를 주입하는 방법을 보여주는 샘플입니다. 또한 web.config에 PerWebRequestLifestyleModule을 등록하는 것을 잊지 마십시오.

+0

감사합니다 마우리시오, 이것은 내가 찾고있는 것입니다. –

+0

줄을 추가해야한다는 점을 다시 강조 할 필요가 있습니다. container.AddFacility (); 이것은 내가 처음 읽기에 당신의 예를 놓친 작은 잡화였습니다. 도움을 주셔서 감사합니다. 매우 유용합니다! – ArtificialGold

+0

Windsor 2.5에서이 경우 FactorySupportFacility는 더 이상 필요하지 않습니다. –

4

이 똑같은 문제가 발생했지만 방금 다른 해결책이 있습니다.

인터페이스 :

public interface IHttpContextProvider 
{ 
    /// <summary> 
    /// Gets the current HTTP context. 
    /// </summary> 
    /// <value>The current HTTP context.</value> 
    HttpContextBase Current { get; } 
} 

구현 :

/// <summary> 
/// A default HTTP context provider, returning a <see cref="HttpContextWrapper"/> from <see cref="HttpContext.Current"/>. 
/// </summary> 
public class DefaultHttpContextProvider : IHttpContextProvider 
{ 
    public HttpContextBase Current 
    { 
     get { return new HttpContextWrapper(HttpContext.Current); } 
    } 
} 

그때 용기에 싱글로서 IHttpContextProvider 레지스터. DI에 관해서는 아직 초보자입니다. 아마도 복잡하게 끝났을 지 모르지만, 이해할 수있는 것으로부터, 어떤 Singleton 구성 요소도 PerWebRequest 라이프 스타일 구성 요소에 의존 할 수 없습니다. 그러나 그것은 모든 예들이하는 것입니다.) 내 솔루션에서는, 난 고립 된 구성 요소에 HttpContext.Current에 의존하고 그 테스트에 관심이 아니에요. 그러나 HTTP 컨텍스트에 액세스해야하는 모든 구성 요소는 IHttpContextProvider에 따라이를 가져올 수 있으며 필요에 따라 쉽게 조롱 할 수 있습니다.

정말 복잡한 일이 있습니까? 아니면 내 해결책에 대한 경고가 있습니까?

+1

이 방법으로 현재 HTTP 컨텍스트에 의존하는 서비스가 PerWebRequest/Transient로 등록되어 있어야한다는 것을 언급해야합니다. – Siewers

+0

잘 작동합니다. 감사합니다. –

관련 문제