14

Ho letto quante più risposte possibili per questo, ma sembrano non avere un dettaglio.Ninject Binding Attribute to Filter with Constructor Argomenti

Il problema è quando si associa un filtro azione (con un servizio iniettato dal controller) a un attributo corrispondente, non sono stato in grado di capire come passare i valori parametro/proprietà dall'attributo al filtro associato. Di seguito è riportato il codice, e al di sotto che il mio finto-codice destinato:

Filtro & attributo

public class AuthorizationFilter : IAuthorizationFilter 
{ 
    private readonly IAuthorizationService _authorizationService; 
    private readonly UserRoles _requiredRoles; // Enum 

    public AuthorizationFilter(IAuthorizationService authorizationService, UserRoles requiredRoles) 
    { 
     _authorizationService = authorizationService; 
     _requiredRoles = requiredRoles; 
    } 

    public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (filterContext.HttpContext.Session == null) 
      HandleUnauthorizedRequest(filterContext); 
     else { 
      var authorized = _authorizationService.IsUserInRole((UserSessionInfoViewModel) filterContext.HttpContext.Session["user"], _requiredRoles); 
      if (!authorized) 
       HandleUnauthorizedRequest(filterContext); 
      // else TODO: deal with cache... 
     } 
    } 
} 

public class RequireRolesAttribute : FilterAttribute 
{ 
    public readonly UserRoles RequiredRoles; 

    public RequireRolesAttribute(UserRoles requiredRoles) 
    { 
     RequiredRoles = requiredRoles; 
    }   
} 

Filtro/Attributo Associazioni

kernel.BindFilter<AuthorizationFilter>(FilterScope.Controller, 0) 
     .WhenControllerHas<RequireRolesAttribute>(); 
kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, 0) 
     .WhenActionMethodHas<RequireRolesAttribute>(); 

Questo dovrebbe fare in modo qualsiasi controller/l'azione decorata con [RolesRequired] è associata al filtro. Fin qui tutto bene. Ora voglio dichiarare tramite l'attributo i ruoli (proprio come lo stock AuthorizeAttribute) e passare quei valori sul filtro che effettivamente fa l'autorizzazione.

previsto/Codice Falso:

[RequireRoles(UserRoles.Author)] 
public ActionResult Index() 
{ 
    // blah 
} 

In particolare,

Che cosa ci vuole per informare l'AuthorizationFilter dei ruoli? Il filtro/ninject può accedere agli argomenti passati al costruttore dell'attributo? Il filtro/ninject può estrarli dagli attributi public property?

Per riferimento, questi articoli sono stati di grande aiuto, ma non rispondere a questa una cosa:

Dependency Injection with Ninject and Filter attribute for asp.net mvc

Custom Authorization MVC 3 and Ninject IoC

BZ, Remo Gloor, altri ... come posso compire Questo?

risposta

19

L'ho capito (grazie alle istruzioni e alla documentazione di Remo).

Utilizzare l'estensione .WithConstructorArgument appropriata per il collegamento a un controller oa un filtro di azione. Per la rilegatura mio filtro azione esempio si presenta:

kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, 0) 
     .WhenActionMethodHas<RequireRolesAttribute>() 
     .WithConstructorArgumentFromActionAttribute<RequireRolesAttribute>("requiredRoles", o => o.RequiredRoles); 

Una volta capito il Func <> firma , tutto è diventato chiaro.Il modo migliore che ho trovato per gestire questa situazione è stato quello di

  1. rendere tipo specifico l'estensione per il mio attributo

    .WithConstructorArgumentFromActionAttribute<TAttribute>() 
    
  2. recuperare il valore dall'oggetto callback (l'attributo) tramite lambda:

    ("argumentName", o => o.PropertyName) 
    
+1

solo il biglietto, applausi – redsquare

+0

Tutte le idee su ciò che deve essere fatto se la classe che deriva da 'FilterAttribute' ha costruttore con parametri multipli (cioè RequireRoles classe nell'esempio precedente avendo costruttore con più parametes) allora come può i parametri sono mappati in '.WithConstructorArgumentFromActionAttribute ()' ?? – Vipresh

+1

Per rendere disponibile il metodo 'BindFilter <>()', è possibile aggiungere un riferimento a 'Ninject.Web.Mvc.FilterBindingSyntax'. – bump

8

e di portare il metodo BindFilter estensione in ambito non dimenticare di aggiungere;

using Ninject.Web.Mvc.FilterBindingSyntax; 
+15

Questa non è una risposta, dovrebbe essere postata come commento alla risposta della soluzione. – angularsen

+0

Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il link per riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - [Dalla recensione] (/ recensione/post di bassa qualità/18739473) – diceler