简体   繁体   中英

Cannot access a disposed object.\r\nObject name: 'ApplicationUserManager'

I have a web API and using Autofac for DI. In startup method, I am configuring auth using app.CreatePerOwinContext (AppDbContext, UserManager and SignInManager). I am also configuring autofac here and registering controllers and other required types and modules.

I am also registering OwinContext with DI and in one of the library used by my API, I am doing constructor injection of IOwinContext

When I make a first API request, Context.GetUserManager() works fine, but after first request it always throws "Cannot access a disposed object.\\r\\nObject name: 'ApplicationUserManager'."

My controllers are registered using InstancePerRequest() My Library is registered using InstancePerLifetimeScope()

Same code works fine with an ASP.Net Web application if I bypass my API and make direct calls to my library code.

I tried so much but I am not able to figure out the proper solution.

Startup.cs class (Web Api)

public partial class Startup
{
       public void Configuration(IAppBuilder app)
        {
                //Add cors middleware
                app.UseCors(CorsOptions.AllowAll);

                //http Configuration
                var config = new HttpConfiguration();
                WebApiConfig.Register(config);

                //Configure authentication
                ConfigureAuth(app);

                //Configure DI Container
                AutofacConfig.Register(app, config);

                app.UseWebApi(config);
        }
       public void ConfigureAuth(IAppBuilder app)
        {
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
        }
}

DI Registration

public class AutofacConfig
    {
        public static void Register(IAppBuilder app, HttpConfiguration config)
        {
            var builder = new ContainerBuilder();

            builder.Register(c => HttpContext.Current.Request.GetOwinContext()).As<IOwinContext>();
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).InstancePerRequest();
            //this is in another module in different library which I am calling from here using builder.RegisterModule
            builder.RegisterType<UserManager>().As<IManager<User>>().InstancePerLifetimeScope();

            //Set the dependency resolver to be Autofac.
            var container = builder.Build();
            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

            // Register the Autofac middleware FIRST, then the Autofac Web API middleware,
            app.UseAutofacMiddleware(container);
            app.UseAutofacWebApi(config);
        }
    }

Here is my UserManager

 public class UserManager: IManager<User>
    {
        private ApplicationUserManager _applicationUserManager;
        private readonly IOwinContext _context;

        protected ApplicationUserManager ApplicationUserManager
        {
            get => _applicationUserManager ?? _context.GetUserManager<ApplicationUserManager>();
            set => _applicationUserManager = value;
        }

        public UserManager(IOwinContext context)
        {
            _context = context;
            ApplicationUserManager = context.GetUserManager<ApplicationUserManager>();
        }

        public User GetById(int? id)
        {
            //This throws System.ObjectDisposedException ('Cannot access a disposed object.Object name: 'ApplicationUserManager'.') after first API request.
            var user = ApplicationUserManager.FindByEmail(entity.UserName);
            return entity;
        }
   }

I finally figured out the problem. UserManager is being shared by multiple applications. API and ASP.Net Web app needed it to be registered using InstancePerRequest() For other apps I registered it using InstancePerLifetimeScope().

Created a module with constructor parameter which takes bool value and registered UserManager using InstancePerRequest() if the parameter is true, otherwise used InstancePerLifetimeScope(). This fixed my problem.

Basically this is what was happening, After every request, ApplicationUserManager in OwinContext was disposed but my UserManager was still the same with the same OwinContext.

public class AutofacConfig
    {
        public static void Register(IAppBuilder app, HttpConfiguration config)
        {
            var builder = new ContainerBuilder();

            builder.Register(c => HttpContext.Current.Request.GetOwinContext()).As<IOwinContext>().InstancePerRequest();
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).InstancePerRequest();
            //this is in another module in different library which I am calling from here using builder.RegisterModule
            builder.RegisterType<UserManager>().As<IManager<User>>().InstancePerRequest();

            //Set the dependency resolver to be Autofac.
            var container = builder.Build();
            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

            // Register the Autofac middleware FIRST, then the Autofac Web API middleware,
            app.UseAutofacMiddleware(container);
            app.UseAutofacWebApi(config);
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM