Problemi Configurazione di StructureMap.MVC5 per lavorare con Identity

Attualmente sto provando a riconfigurare StructureMap nella nostra applicazione dopo l’aggiornamento da una vecchia versione (2.6) che non è mai stata implementata correttamente in primo luogo. Sono nuovo nell’usare i contenitori DI per cominciare e sto trovando la documentazione per le versioni di StructureMap più difficili da trovare. Ho disinstallato la vecchia versione 2.6 di StructureMap e installato StructureMap.MVC5 (dato che sto usando MVC5).

Ciò di cui sto avendo problemi è l’AccountController. Ho strutturato StructureMap per utilizzare il costruttore senza parametri, ma quando la mia applicazione tenta di creare UserManager, ottengo un InvalidOperationException , "No owin.Environment item was found in the context."

Ovviamente ho bisogno di una configurazione aggiuntiva per StructureMap, ma non ho idea di cosa / come. Sono in grado di trovare un milione di fonti per questo errore, il che suggerisce l’aggiunta di un tag in web.config, ma nessuno di essi sembra essere specifico per DI – e ho solo questo problema quando utilizzo StructureMap anziché lasciare che il framework crei il controller.

Di seguito è riportato il codice pertinente; quella sezione di AccountController è solo il codice del modello di magazzino.

AccountController.cs

  private ApplicationUserManager _userManager; public AccountController() { } public AccountController(ApplicationUserManager userManager) { UserManager = userManager; } public ApplicationUserManager UserManager { get { // This is where the exception is thrown return _userManager ?? HttpContext.GetOwinContext().GetUserManager(); } private set { _userManager = value; } } 

DefaultRegistry.cs

  public DefaultRegistry() { Scan( scan => { scan.TheCallingAssembly(); scan.WithDefaultConventions(); scan.With(new ControllerConvention()); }); For() .Use() .LifecycleIs() .Ctor("ConnectionString") .Is(ConfigurationManager.ConnectionStrings["MyContext"].ConnectionString); For() .Use() .SelectConstructor(() => new AccountController()); } 

Come ha sottolineato @Erik Funkenbusch, stavo facendo cose in competizione. Ho finito per rendere UserManager una proprietà automatica, rimosso il costruttore senza parametri e lasciato che StructureMap iniettasse ApplicationUserManager.

  public ApplicationUserManager UserManager { get; private set; } public AccountController(ApplicationUserManager userManager) { UserManager = userManager; } 

Quindi, ho semplicemente avuto bisogno di configurare IUserStore e DbContext che Identity utilizza in DefaultRegistry.cs:

  For>() .Use>() .LifecycleIs(); For() .Use(() => new ApplicationDbContext()) .LifecycleIs(); 

Questo era tutto ciò che dovevo fare per far funzionare StructureMap.MVC con Identity.

Parte del mio hangup iniziale era che non mi ero reso conto del modo in cui StructureMap.MVC (e altri contenitori DI) funzionava. (Vedi la mia domanda correlata ). Mi aspettavo che funzionasse solo con il mio AccountController di riserva che è stato inizializzato dal framework (e ho pensato che la creazione di oggetti intercettata magicamente per iniettare tutto ciò che avevo configurato), non rendendosi conto che StructureMap deve inizializzare i controller stessi ordina che esegua l’iniezione del costruttore. Così, quando mi sono imbattuto in problemi, ero A. Sorpreso che StructureMap avesse qualcosa a che fare con il mio AccountController in primo luogo (dal momento che non stavo configurando esplicitamente l’iniezione per nessuno dei suoi parametri – solo per il mio repository usato in altri controller), e B. Non stavo pensando di cambiare il mio codice ma piuttosto di pensare a come configurare StructureMap. Risultò che avevo bisogno di fare entrambe le cose. Fortunatamente, è stata una modifica facile e ho imparato un po ‘di più su come funzionano i contenitori DI.