2013-02-22 9 views
8

In MVC, un ModelValidatorProvider viene istanziato e chiamato per convalidare un modello su ogni richiesta. Ciò significa che in un ambiente DI può assumere dipendenze da oggetti nell'ambito di una singola richiesta, ad esempio un contesto Unità di lavoro o Database. In Web API, sembra essere stato modificato in modo significativo. Invece di essere istanziato per richiesta, lo ModelValidatorProvider sembra essere di lunga durata e istanziato all'interno dell'avvio dell'applicazione. Quindi WebAPI memorizza nella cache i risultati del tipo per ModelValidatorProvider, il che significa che lo ModelValidator non può assumere alcuna dipendenza da DI.DependencyResolver per richiesta in Web API

Sto cercando di implementare il mio ModelValidator di utilizzare una fabbrica con Service Locator (per favore, commenti automatici 'anti-modello'!). Questo mi permetterebbe di costruire un oggetto validatore interno all'interno di ogni richiesta, che sarebbe in grado di prendere le dipendenze dal contenitore. Tuttavia, non riesco a mettere in attesa un Dependency Resolver o un container con scope per la richiesta corrente all'interno di questo ModelValidator che è essenzialmente definito come Singleton. Ho provato ad usare GlobalConfiguration.Configuration.DependencyResolver, ma questo solo rendimenti servizi a livello globale con ambito (dal campo di applicazione della radice, anche mentioned here)

sto lavorando in Autofac, quindi una soluzione specifica per autofac sarebbe adatto (ad esempio MVC ha AutofacDependencyResolver.Current , che utilizza internamente DependencyResolver.GetService). Non vi sono equivalenti disponibili nell'integrazione WebAPI, presumibilmente a causa del motivo sopra menzionato in cui il globale DependencyResolver restituisce solo servizi con ambito globale.

Il motivo per cui sto provando a farlo (oltre che per uso personale) è implementare l'integrazione dell'API Web per FluentValidation, che attualmente non esiste. Ci sono stati finora due tentativi, ma nessuno di questi gestisce il problema di Dependency Injection e invece si traduce in un singolo ModelValidator statico.

Le cose che ho provato finora:

  • Utilizzando GlobalConfiguration.Configuration.DependencyResolver (restituisce oggetti dal campo di applicazione della radice)
  • Facendo una dipendenza da Func<IComponentContext> (restituisce sempre il contesto radice)

In una risposta che è stata rimossa, è stato suggerito di rimuovere il servizio IModelValidatorProvider dalla configurazione dell'API Web. Questo doveva essere fatto usando la reflection poiché l'interfaccia e le classi di implementazione sono tutte definite come interne, ma ha fatto funzionare meglio i validatori (perché il ModelValidator è stato costruito per richiesta). Tuttavia, c'è un notevole calo delle prestazioni nel farlo in questo modo a causa dell'uso della reflection per verificare i validatori sul modello e su ogni proprietà che ha, quindi non voglio prendere questa opzione.

La risposta di Filip W suggerisce l'uso di HttpRequestMessage per ottenere l'ambito di dipendenza, ma non ho trovato nulla come HttpRequestMessage.Current che fornirebbe l'accesso a questo oggetto da un oggetto di lunga durata - se ciò fosse possibile, credo che tutto sarebbe cadere al suo posto.

risposta

3

Per ottenere la portata attuale dipendenza, è necessario utilizzare (sorpresa, sorpresa :) GetDependencyScope() della corrente HttpRequestMessage (più su cui è possibile leggere on MSDN) invece di GlobalConfiguration.

Ho bloggato circa Web API per-request dependency scope qualche tempo fa, che dovrebbe essere utile.

+6

Sembra che potrebbe essere più vicino alla soluzione, ma come posso ottenere HttpRequestMessage? Questo è da una classe di lunga data. Googling suggerisce che anche questo non è possibile. – Richard