7

Ich suchte lange nach einer Lösung für mein Problem. Ich habe ein benutzerdefiniertes AuthorizeAttribute, das eine Abhängigkeit von einem "Dienst" benötigt, der Zugriff auf einen DbContext hat. Leider funktioniert die Dependency Injection im benutzerdefinierten AuthorizeAttribute nicht und war immer null.asp.net MVC5 - Dependency Injection und AuthorizeAttribute

Ich kam mit einer (für mich) akzeptablen Lösung. Jetzt möchte ich wissen, ob meine Lösung unvorhergesehenes Verhalten verursachen kann?

Global.asax.cs

CustomAuthorizeAttribute.AuthorizeServiceFactory =() => unityContainer.Resolve<AuthorizeService>(); 

CustomAuthorizeAttribute.cs

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] 
    public class CustomAuthorizeAttribute : AuthorizeAttribute 
    { 
     public static Func<AuthorizeService> AuthorizeServiceFactory { get; set; } 

     public Privilege Privilege { get; set; } 

     protected override bool AuthorizeCore(HttpContextBase httpContext) 
     { 
      bool authorized = base.AuthorizeCore(httpContext); 
      if (!authorized) 
      { 
       return false; 
      } 

      return AuthorizeServiceFactory().AuthorizeCore(httpContext, Privilege); 
     } 
    } 

AuthorizeService.cs

public class AuthorizeService 
{ 
    [Dependency] 
    public UserService UserService { private get; set; } 

    public bool AuthorizeCore(HttpContextBase httpContext, Privilege privilege) 
    { 
     ApplicationUser user = UserService.FindByName(httpContext.User.Identity.Name); 
     return UserService.UserHasPrivilege(user.Id, privilege.ToString()); 
    } 
} 

Ist das eine akzeptable Lösung? Wird es in der Zukunft zu unangenehmen Problemen kommen oder gibt es möglicherweise eine bessere Möglichkeit, Dependency Injection in einem benutzerdefinierten AuthorizeAttribute zu verwenden?

Antwort

8

Ich habe ein benutzerdefiniertes AuthorizeAttribute, das eine Abhängigkeit zu einem "Dienst" benötigt, der Zugriff auf einen DbContext hat. Leider funktionierte die Abhängigkeit Injection im benutzerdefinierten AuthorizeAttribute nicht und war immer null.

Eine Implementierung von IControllerFactory im System.Web.Mvc Namespace erstellt Instanzen Ihre Controller für Web-Anfragen. Die Controller Factory verwendet System.Web.Mvc.DependencyResolver, um Abhängigkeiten in jedem Controller aufzulösen.

jedoch ActionFilters/Attribut im MVC pipeline nicht vom Controller Factory erstellt so Abhängigkeiten nicht aufgelöst werden mit System.Web.Mvc.DependencyResolver. Deshalb war Ihre Abhängigkeit immer null.

Jetzt ist System.Web.Mvc.DependencyResolverpublic und static, so dass Sie selbst darauf zugreifen können.

public class AuthorizeService : AuthorizeAttribute 
    { 
     private UserService UserService 
     { 
      get 
      { 
       return DependencyResolver.Current.GetService<UserService>(); 
      } 
     } 

     public bool AuthorizeCore(HttpContextBase httpContext, Privilege privilege) 
     { 
      ApplicationUser user = UserService.FindByName(httpContext.User.Identity.Name); 
      return UserService.UserHasPrivilege(user.Id, privilege.ToString()); 
     } 
    } 

Ihre Unter der Annahme, UserService hat eine Abhängigkeit Umfang WebRequest, also seine Lebensdauer One Pro Web-Anfrage ist und auf die Lebensdauer von HttpContext einer Web-Anfrage gebunden wird dies nicht ein neues UserService konstruieren, wenn man hat wurde zuvor oder nachher aufgelöst, wenn UserService zum ersten Mal für die angegebene Webanfrage aufgelöst wurde.