Ayman Ayman - 1 year ago 600
ASP.NET (C#) Question

Usermanager.DbContext already disposed in Middleware

I have the below Middleware in an Asp.Net Core application where I require a

to be injected in it. When I try to query for a user
, I get the following exception:

ObjectDisposedException: Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur is you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'ApplicationDbContext'.

My Middleware:

namespace MyApp
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;

public class MyMiddleware<TUser, TRole>
where TUser : class where TRole : class
private readonly RequestDelegate _next;
private readonly UserManager<TUser> _userManager;
private readonly RoleManager<TRole> _roleManager;
private readonly IOptions<IdentityOptions> _optionsAccessor;

public UserIdentityMiddleware(RequestDelegate next, UserManager<TUser> userManager,
RoleManager<TRole> roleManager, IOptions<IdentityOptions> optionsAccessor)
_next = next;
_userManager = userManager;
_roleManager = roleManager;
_optionsAccessor = optionsAccessor;

public async Task Invoke(HttpContext context)
var user = await _userManager.FindByIdAsync("1");

var claimsPrincipal = await new UserClaimsPrincipalFactory<TUser, TRole>(
_userManager, _roleManager, _optionsAccessor).CreateAsync(user);


await _next(context);

Answer Source

The problem happens because the middleware itself is a Singleton, so its internal dependencies also need to be singleton, but the identity classes like UserManager are scoped per request by default, that is how they are registered in Startup.ConfigureServices and also the dependencies for UserManager such as dbContext are also scoped per request.

Generally scoped per request is what you want for those objects, especially if they are also used in other places such as controllers.

One solution is instead of having your middleware take a constructor dependency on UserManager, you could access only when needed from inside the Invoke method, the syntax would be something like this:

var userManager = context.RequestServices.GetService(UserManager<TUser>);

that might not be exactly right syntax and you probably have to specify the actual user type

the downside is that this would be the servicelocator pattern but it would solve the problem because then you would get a UserManager per request which is how it is supposed to be scoped

actually I think you can avoid the service locator pattern because the Invoke method is injectable, you can add additional dependencies to the method signature like this:

public async Task Invoke(HttpContext context, UserManager<TUser> userManager)

but again probably have to provide the actual type rather than TUser

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download