7

WebAPI projesindeki denetleyiciler için IoC'yi yönetmek üzere Windsor'u kullanıyorum. Denetleyici bağımlılıklarını çözmek için güzel çalışan bir DependencyResolver var, ancak şimdi kimlik doğrulamasını yönetmek için kullanıyorum özel bir eylem filtresine bağımlılıkları enjekte etmeyi arıyorum.ASP.NET 4 RC WebAPI'de bağımlılık enjeksiyonunu eylem filtrelerine nasıl yapabilirim?

Özel bir ActionInvoker kullanmayı inceledim, ancak WebAPI'nin çalıştırılmadan önce özel eylem filtresi özniteliğinde özellik bağımlılıklarını çözme konusunda nasıl giderim yapacağını arabirimden net değil. MVC 4 RC'de bunun nasıl yapıldığına dair iyi bir örnek var mı?

DÜZENLEME: Filtreler üzerinde yapıcı enjeksiyonu yapamayacağınızın farkındayım, çünkü bunlar öznitelikler ve bu nedenle .NET çerçevesiyle örneklendirildi - ama umarım AFTER şu anda gerçekleşen yürütme yaşam döngüsünde bir nokta var. filtre başlatılır, ancak filtrelerin genel özellikleri arasında numaralandırmak ve gerekli hizmetleri enjekte etmek için bazı özel kodları çalıştırabildiğimden ÖNCE.

+0

IMHO çok iyi bir şekilde ayrıştırılmış sürümü bu [soru (ve yanıt) - ASP.NET MVC IFilterProvider ve endişeleri ayrılığı] 'da açıklanmıştır] (http://stackoverflow.com/questions/10708565/asp-net-mvc-ifilterprovider- ve ayırma-of-endişeleri). –

cevap

10

Eylem filtreleri niteliklerdir. .NET özniteliğinde, örnekleme işlemi .NET çalışma zamanı tarafından yönetilir ve üzerinde denetiminiz yoktur. Dolayısıyla, bir olasılık size karşı size tavsiyede bulunacağım Poor Man's Dependency Injection'u kullanmaktır.

başka olasılık bir işaretleyici niteliğini kullanmaktır:

public class MyActionFilterAttribute : Attribute 
{ 

} 

ve ardından yapıcı enjeksiyon kullanarak eylem filtresi vardır:

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

ve sonra Application_Start küresel eylem süzgeç olarak kayıt:

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

Darin - bunun için teşekkürler; Servis bulucu yaklaşımını çoktan denedim ama biraz daha temiz bir şey arıyorum - aradığımı umarsız bir şekilde açıklığa kavuşturan soruyu düzenle. –

+0

@DylanBeattie, hayır, eğer kurucu enjeksiyonu kullanmak istiyorsanız (bu, gerekli bağımlılıkları sınıflara enjekte etmenin doğru yolu), özniteliklerde maalesef olmayan sınıfın örneklenmesi üzerinde kontrol sahibi olmanız gerekir. İşte bu yüzden işaretçi arayüzünü cevabımda gösterildiği gibi kullanabilirsiniz. –

+0

Filtreleri konteynerinizde kaydederseniz ve global.asax'da kapsayıcıyı oluşturursanız, filtreleri çözümlemek için kabı kullanabilirsiniz. _container.ResolveAll (t) .Cast () .ForEach (GlobalConfiguration.Configuration.Filters.Add) –

4

Aynı problemi yaşadım, ancak r ServiceLocator bunun için (DependencyResolver.GetService), onun çerçevesinde bana öyle geliyor gibi geçerli yaklaşımdır

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

olmak ve burada bu özellik için bir testtir için, bir ağrı biraz ama mümkün

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

Bu iyi bir yol olarak kabul edilmez, –

+0

ile alay edilemez, ancak –

+0

yapabilirsiniz Belki de en iyi yol değil, ama Bazı durumlarda bu tek yol olabilir. –

İlgili konular