7

Windsor를 사용하여 WebAPI 프로젝트에서 컨트롤러 용 IoC를 관리하고 있습니다. DependencyResolver가 컨트롤러 종속성을 해결하기 위해 잘 작동하고 있지만 이제는 인증 관리에 사용하는 사용자 지정 동작 필터에 종속성을 주입하려고합니다.ASP.NET 4 RC WebAPI의 작업 필터에 종속성 삽입을 수행하려면 어떻게해야합니까?

사용자 지정 ActionInvoker를 사용했지만 인터페이스에서 WebAPI가 실행되기 전에 사용자 지정 동작 필터 특성에 대한 속성 종속성을 해결하는 방법을 사용하고 있는지 분명하지 않습니다. 누구나 MVC 4 RC에서이를 수행하는 좋은 예가 있습니까?

EDIT : .NET Framework에 의해 특성화되어 인스턴스화되기 때문에 필터에 생성자 삽입을 할 수 없다는 것을 알고 있습니다. 그러나 실행주기의 일부 지점이 필터가 인스턴스화되었지만 실행되기 전에 사용자 정의 코드를 실행하여 필터의 공용 속성을 열거하고 필요한 서비스를 주입 할 수 있습니다.

+0

IMHO 아주 좋은 분리 된 버전은이 [질문 및 답변 - ASP.NET MVC IFilterProvider 및 관심 분리]에서 설명합니다. http://stackoverflow.com/questions/10708565/asp-net-mvc-ifilterprovider- 및 분리의 우려). –

답변

10

조치 필터는 속성입니다. .NET 속성에서 인스턴스화 프로세스는 .NET 런타임에 의해 관리되며 사용자는이를 제어 할 수 없습니다. 그래서 한 가지 가능성은 내가 개인적으로 조언하고자하는 Poor Man's Dependency Injection을 사용하는 것입니다.

다른 가능성은 마커 특성을 사용하는 것이다

public class MyActionFilterAttribute : Attribute 
{ 

} 

을 다음 생성자 주입하여 작용 필터를 가지고

public class MyActionFilter : ActionFilterAttribute 
{ 
    private readonly IFoo _foo; 
    public MyActionFilter(IFoo foo) 
    { 
     _foo = foo; 
    } 

    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     if (actionContext.ActionDescriptor.GetCustomAttributes<MyActionFilterAttribute>().Any()) 
     { 
      // The action is decorated with the marker attribute => 
      // do something with _foo 
     } 
    } 
} 

하고 Application_Start 글로벌 액션 필터로 등록을 :

IFoo foo = .... 
GlobalConfiguration.Configuration.Filters.Add(new MyActionFilter(foo)); 
+0

Darin - 감사합니다. 나는 서비스 로케이터 접근법을 이미 시도해 왔지만 좀 더 깨끗한 것을 찾고있다. 내가 찾고있는 것을 명확히 해줄 내 질문에 대한 편집을 참조하라. –

+0

@DylanBeattie, 아니요, 생성자 삽입 (필요한 의존성을 클래스에 주입하는 적절한 방법입니다)을 사용하려면 불행히도 속성의 경우가 아닌 클래스의 인스턴스화를 제어해야합니다. 그래서 내 대답과 같이 마커 인터페이스를 사용할 수 있습니다. –

+0

컨테이너에 필터를 등록하고 global.asax에서 컨테이너를 만들면 컨테이너를 사용하여 필터를 확인합니다 (예 : _container.ResolveAll() .Cast () .ForEach (GlobalConfiguration.Configuration.Filters.Add) –

4

나는 같은 문제가 있었지만 R ServiceLocator이 대한 (DependencyResolver.GetService)는 자사의 프레임 워크에 나에게 보인다 유효한 접근 방식을

public class RequiresSessionAttribute : 
    ActionFilterAttribute 
{ 
    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     var sessionService = 
      (ISessionService) actionContext 
        .ControllerContext.Configuration.DependencyResolver 
        .GetService(typeof (ISessionService)); 

     var sessionId = HttpUtility 
      .ParseQueryString(actionContext.Request.RequestUri.Query) 
      .Get("sessionId"); 

     if (sessionId == null 
      || !sessionService.IsValid(sessionId)) 
      throw new SessionException(); 

     base.OnActionExecuting(actionContext); 
    } 
} 

을하고 여기에이 속성에 대한 테스트되는, 고통의 비트 만 가능

public class requires_sessionId 
{ 
    [Fact] 
    void can_call_action_with_session_id() 
    { 
     var context = GetContext("http://example.com/?sessionId=blaa"); 

     var sut = new RequiresSessionAttribute(); 

     Assert.DoesNotThrow(
      () => sut.OnActionExecuting(context)); 
    } 

    [Fact] 
    void can_not_call_action_without_session_id() 
    { 
     var context = GetContext("http://example.com/"); 

     var sut = new RequiresSessionAttribute(); 

     Assert.Throws<SessionException>(
      () => sut.OnActionExecuting(context)); 
    } 

    HttpActionContext GetContext(string url) 
    { 
     var sessionServiceMock = new Mock<ISessionService>(); 
     sessionServiceMock 
      .Setup(x => x.IsValid(It.IsAny<string>())) 
      .Returns(true); 

     var dependancyResolverMock = new Mock<IDependencyResolver>(); 
     dependancyResolverMock 
      .Setup(x => x.GetService(It.IsAny<Type>())) 
      .Returns(sessionServiceMock.Object); 

     var config = new HttpConfiguration 
       { 
        DependencyResolver = dependancyResolverMock.Object 
       }; 
     var controllerContext = new HttpControllerContext 
       { 
        Configuration = config, 
        Request = new HttpRequestMessage(
           HttpMethod.Get, 
           url) 
       }; 

     return 
      new HttpActionContext 
       { 
        ControllerContext = controllerContext, 
       }; 
    } 
} 
+1

좋은 방법으로 간주되지 않습니다. –

+0

을 쉽게 조롱 할 수는 없지만 –

+0

일 수 있습니다. 어떤 경우에는 유일한 방법 일 수도 있습니다. –

관련 문제