2015-10-21 16 views
12

ho scritto il mio middleware personalizzati che aggiungo inAccesso DbContext in Middleware in ASP.NET 5

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
{ 
    //... 
    app.UseAutologin(); 
    app.UseMvc(routes => 
    { 
     //... 

Così è l'ultima prima del middleware MVC entra in gioco.

Nel metodo Invoke del mio middleware, desidero accedere (indirettamente) allo DbContext.

public async Task Invoke(HttpContext context) 
    { 
    if (string.IsNullOrEmpty(context.User.Identity.Name)) 
    { 
     var applicationContext = _serviceProvider.GetService<ApplicationDbContext>(); 
     var signInManager = _serviceProvider.GetService<SignInManager<ApplicationUser>>(); 
     var result = await signInManager.PasswordSignInAsync(_options.UserName, _options.Password, true, false); 
    } 

    await _next(context); 
    } 

Quasi ogni volta che ottengo la seguente eccezione:

InvalidOperationException: Si è tentato di utilizzare il contesto mentre è in fase di configurazione. Un'istanza DbContext non può essere utilizzata all'interno di OnConfiguring poiché è ancora in fase di configurazione in questo punto.

Ora questo è chiaramente sollevato dal metodo PasswordSignInAsync. Ma come posso assicurarmi che il modello sia stato creato prima di fare queste cose?

Forse non ero del tutto chiaro: non voglio usare lo stesso DbContext - lo PasswordSignInAsync lo utilizza durante la verifica dell'utente e della password.

+0

ho il un errore . Hai trovato una correzione per favore. – aguetat

+0

Cosa stai cercando di ottenere? – mayu

risposta

5

Che cosa succede se si inietta il ApplicationDbContext e SignInManager<ApplicationUser> attraverso il metodo Invoke:

public async Task Invoke(HttpContext context, ApplicationDbContext applicationContext, SignInManager<ApplicationUser> signInManager) 
{ 
    if (string.IsNullOrEmpty(context.User.Identity.Name)) 
    { 
     var result = await signInManager.PasswordSignInAsync(_options.UserName, _options.Password, true, false); 
    } 

    await _next(context); 
} 

questo modo i servizi vengono risolti dal campo di applicazione corretta. Ho notato che in realtà non usi lo ApplicationDbContext ovunque, solo lo SignInManager. Ne hai davvero bisogno?

+0

Il "SignInManager" lo usa, ecco perché ho ricevuto l'errore ... –

1

Questo errore si verifica probabilmente perché qualsiasi middleware funge da singleton. Devi evitare di utilizzare le variabili membro nel tuo middleware. Sentitevi liberi di iniettare in Task Invoke, ma non memorizzare il valore di iniezione in un oggetto membro.

See: Saving HttpContext Instance in Middleware, Calling services in Middleware

sono stato in grado di aggirare questo me stesso, per creare una classe che ho potuto poi passare ad altri metodi nella mia middleware:

public async Task Invoke(HttpContext context, IMetaService metaService) 
    { 
      var middler = new Middler 
      { 
       Context = context, 
       MetaService = metaService 
      }; 

      DoSomething(middler); 
    }