7

Ho cercato a lungo una soluzione per il mio problema. Ho un AuthorizeAttribute personalizzato che ha bisogno di una dipendenza per un "Servizio" che ha accesso a un DbContext. Purtroppo la Iniezione di Dipendenza non ha funzionato nell'autorizzazione AuthorizeAttribute e era sempre nullo.asp.net MVC5 - Iniezione delle dipendenze e AuthorizeAttribute

Mi è venuta una (per me) soluzione accettabile. Ora voglio sapere se la mia soluzione può causare un comportamento imprevisto?

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

Questa è una soluzione accettabile? In futuro mi imbatterò in problemi fastidiosi o forse c'è un modo migliore di usare Dependency Injection in un AuthorizeAttribute personalizzato?

risposta

8

Ho un AuthorizeAttribute personalizzato che richiede una dipendenza da un "Servizio" che ha accesso a un DbContext. Purtroppo l'iniezione Dipendente non ha funzionato nell'autorizzazione AuthorizeAttribute personalizzata ed è sempre stata null.

Un'implementazione del IControllerFactory nel System.Web.Mvc namespace crea istanze tuoi Controller per le richieste Web. Controller Factory utilizza System.Web.Mvc.DependencyResolver per risolvere le dipendenze in ciascun controller.

Tuttavia, ActionFilters/Attributi nel MVC pipeline non sono creati dalla fabbrica di controllo in modo da dipendenze non vengono risolte utilizzando System.Web.Mvc.DependencyResolver. Questo è il motivo per cui la tua dipendenza era sempre null.

Ora, System.Web.Mvc.DependencyResolver è public e static in modo da poter accedere da soli.

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

Assumendo che il UserService ha una portata dipendenza WebRequest, vale a dire la sua durata è Uno per richiesta web e legato alla vita di HttpContext di una richiesta Web questo non costruire una nuova UserService se uno ha è stato risolto in precedenza o in seguito se è la prima volta che UserService è stato risolto per la richiesta web specificata.

Problemi correlati