2009-08-18 12 views
6

I am castle Windsor e funziona perfettamente per i costruttori di controller nel passaggio nel repository in uso.Come passare il repository a un attributo autorizza in ASP.NET MVC

private IStoryRepository Repository; 
public StoryController(IStoryRepository Repository) 
{ 
    this.Repository = Repository;     
} 

ora ho un'azione che si trova nella zona di admin per visualizzare il menu di amministrazione principale. Ho usato un attributo di autorizzazione personalizzato che sarà solo verificare che l'utente connesso sia un amministratore (solo una bandiera IsAdmin nella tabella utenti)

[AdminAuthorize] 
public ActionResult Menu() 

private IStoryRepository Repository; 
/// <summary> 
/// Initializes a new instance of the <see cref="AdminAuthorizeAttribute"/> class. 
/// </summary> 
public AdminAuthorizeAttribute(IStoryRepository Repository) 
{ 
    this.Repository = Repository; 
} 

/// <summary> 
/// Checks if the user is authorised 
/// </summary> 
/// <param name="httpContext">The HTTP context.</param> 
/// <returns> 
/// <c>true</c> if authorized; otherwise, <c>false</c>. 
/// </returns> 
protected override bool AuthorizeCore(HttpContextBase httpContext) 
{ 
    return this.Repository.UserIsAdmin(httpContext.User.Identity.Name); 
} 

Come posso ottenere Castello di passare il repository nei attributo costruttore di simile fa per un costruttore di controller?

risposta

1

Fondamentalmente hai due opzioni. Avvolgi il filtro in un proxy, un buon esempio di questo può essere trovato here.

Oppure, all'interno del filtro personalizzato è possibile effettuare una chiamata contenitore esplicita. Ad esempio, utilizzando StructureMap (non ho il castello ampiamente utilizzato)

ObjectFactory.GetInstance(IStoryRepository) 

Ci può essere una terza via, che è quello di estendere l'ActionInvoker di fare l'iniezione, ma io non sono sicuro di come questo sarebbe stato fatto.

0

Mi potrebbe valere la pena di guardare il progetto FluentMVC. Ti permette di configurare gli attributi all'avvio e poiché utilizza la funzione windsor sotto il cofano dovrebbe consentire che questo venga iniettato facilmente in pritty. Per esempio

FluentMvcConfiguration.Configure = x => { 
           x.UsingControllerFactory(new WindsorControllerFactory());                x.WithFilter<HandleErrorAttribute>(); 
           x.WithFilter<AuthorizeAttribute>(
            Except 
             .For<AccountController>(ac => ac.LogOn()) 
             .AndFor<AccountController>(ac => ac.LogOn(null, null, false, null)) 
             .AndFor<HomeController>()); 
          }; 

Il codice qui sopra aggiungere l'AuthorizeAttribute a tutte le azioni, ad eccezione di login e il controller di casa

Non sono sicuro che lo stato attuale del progetto è, ma hanno usato un paio di volte e funziona abbastanza bene per me.

0

Il problema è che gli attributi sono costruiti per riflessione anziché tramite chiamate che possono essere intercettate e sostituite con chiamate che delegano al contenitore.

Esistono numerosi approcci che possono essere utilizzati per creare filtri in grado di supportare DI, il più semplice IMHO è quello di estendere l'action invoker e sovrascrivere GetFilters, fornendo un'implementazione che utilizza l'attributo per determinare il tipo di filtro e quindi risolvere quel tipo dal contenitore. Un'implementazione di questo approccio può essere vista in MvcTurbine (http://mvcturbine.codeplex.com/sourcecontrol/changeset/view/37298?projectName=mvcturbine#758440).

0

Perché non si ottiene l'oggetto IRepository da un metodo factory statico all'interno del costruttore del filtro? Basta usare il metodo factory in un modo che permetta a DI di fare il suo lavoro.

DI funzionerà sul metodo "gateway" anziché sull'approccio standard "parametro costruttore".

Problemi correlati