Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing DbContext in Middleware in ASP.NET 5

Tags:

I wrote my custom middleware which I add in

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

So it is the last middleware before the Mvc comes into play.

In my middleware's Invoke method I want to (indirectly) access the 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);
  }

Nearly every time I get the following exception:

InvalidOperationException: An attempt was made to use the context while it is being configured. A DbContext instance cannot be used inside OnConfiguring since it is still being configured at this point.

Now this is clearly raised by the PasswordSignInAsync method. But how can I ensure that the model was created before doing such things?

Maybe I was not entirely clear: I don't want to use the DbContext myself - the PasswordSignInAsync uses it when verifying the user and password.

like image 874
Jan-Patrick Ahnen Avatar asked Oct 21 '15 07:10

Jan-Patrick Ahnen


Video Answer


2 Answers

What if you inject the ApplicationDbContext and SignInManager<ApplicationUser> through the Invoke method:

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);
}

This way you the services are resolved from the correct scope. I notice you don't actually use the ApplicationDbContext anywhere, just the SignInManager. Do you really need it?

like image 170
Henk Mollema Avatar answered Sep 20 '22 19:09

Henk Mollema


This error is likely occurring because any middleware acts as a singleton. You have to avoid using member variables in your middleware. Feel free to inject into the Task Invoke, but don't store the inject value into a member object.

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

I was able to get around this myself, by creating a class that I could then pass into other methods in my middleware:

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

            DoSomething(middler);
    }
like image 34
michaelb Avatar answered Sep 20 '22 19:09

michaelb