.Net Core 2.1 - Cannot access a disposed object.Object name: 'IServiceProvider'

33,827

Solution 1

I would suggest that instead of calling services.GetService<IHttpContextAccessor>(), inject IHttpContextAccessor to the constructor and use aprivate field to store the value.

public AppContractResolver(IServiceProvider services, 
                           IHttpContextAccessor httpContextAccessor)
{
   _services = services;
   this.httpContextAccessor = httpContextAccessor;
}

Also HttpContextAccessor has to be registered manually. In RegisterServices in Startup.cs add, services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

Solution 2

In my case issue was in Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider services)
{
   var svc = services.GetService<IService>(); // <-- exception here
}

just replace services.GetService<>() with app.ApplicationServices.GetService<>()

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
   var svc = app.ApplicationServices.GetService<IService>(); // no exception
}

hope it helps

Solution 3

If you create any transient service, such as services.AddTransient... then .net core will dispose the service provider. This is a bug as of .net core 2.2.

Solution 4

For me it works with:

 public void ConfigureServices(IServiceCollection services)
{
  …
  services.AddHttpContextAccessor();
  …
}

and then:

     public void Configure(IApplicationBuilder app, IHttpContextAccessor accessor)
    {
    ...
    ...accessor.HttpContext.RequestService

     ...

    }

Solution 5

I was getting this error and it took a long time to resolve, so I am going to post it here.

Here is the code that was throwing the error:

using var context = this.DbFactory.CreateDbContext();                
SqlParameter[] parameter =
{
    new SqlParameter("@ord_cust_id", ordCustId)
};
products = await context.GetProduct.FromSqlRaw<ProductEntity>($"{spName}  @ord_cust_id", parameter).AsNoTracking().ToListAsync();

The exception that was thrown was on the last line. It made no sense as the context was being created by the DbFactory, and so there is no way that it could be disposed already.

After a lot of searching, the scope of the DbFactory was found to be "Transient" so that was changed to Singleton, and the exception was resolved.

This is the code in startup:

 services.AddDbContextFactory<CDSEntities>(options =>
 {                
    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
 }, ServiceLifetime.Singleton); //changed to Singlton instead of Transient
Share:
33,827

Related videos on Youtube

Luuk Wuijster
Author by

Luuk Wuijster

Currently in school. (Windesheim)

Updated on July 09, 2022

Comments

  • Luuk Wuijster
    Luuk Wuijster almost 2 years

    I just migrated .NET Core 2.0 to .NET Core 2.1. Everything went fine, but when I try to login now I get the folowing error:

    • $exception {System.ObjectDisposedException: Cannot access a disposed object. Object name: 'IServiceProvider'.

    This happens in this bit of code:

    public class AppContractResolver : DefaultContractResolver
    {
    
        private readonly IServiceProvider _services;
    
        public AppContractResolver(IServiceProvider services)
        {
            _services = services;
        }
    
        protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
        {
            var httpContextAccessor = _services.GetService<IHttpContextAccessor>();
            var user = httpContextAccessor.HttpContext.User;
    
            List<JsonProperty> properies = base.CreateProperties(type, memberSerialization).ToList();
    
            properies = FilterOneClaimGranted(type, properies, user);
    
            return properies;
        }
    

    It happens on this line:

    var httpContextAccessor = _services.GetService<IHttpContextAccessor>();
    

    This did work on .NET Core 2.0

    I have tried adding the HttpContextAccessor to my startup, but that did not work.

    So, how do I fix this?

    Let me know if you need more code. I will happily provide more, but I don't know what you might or might not need, so therefor I did not add a lot of code.'

    EDIT

    I have added services.AddHttpContextAccessor(); to my startup, but that does not seem to work. Still getting the error.

    EDIT 2:

    Full stacktrace:

    - $exception    {System.ObjectDisposedException: Cannot access a disposed object.
    Object name: 'IServiceProvider'.
       at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException()
       at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
       at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
       at WebAPI.Extensions.AppContractResolver.CreateProperties(Type type, MemberSerialization memberSerialization) in C:\Users\luukw\Desktop\stage\blacky-api\Blacky\Extensions\Resolver\AppContractResolver.cs:line 25
       at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateObjectContract(Type objectType)
       at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract(Type objectType)
       at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
       at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract(Type type)
       at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.GetContractSafe(Type type)
       at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
       at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
       at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
       at Microsoft.AspNetCore.Mvc.Formatters.JsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)}    System.ObjectDisposedException
    
    • Gibbon
      Gibbon almost 6 years
      just wanting to check, are you registering it in the .net core 2.1 way of calling services.AddHttpContextAccessor();
    • Luuk Wuijster
      Luuk Wuijster almost 6 years
      I have tried adding it, but did not work. Still got the same error
    • Vitaly
      Vitaly almost 6 years
      Instead calling AddHttpContextAccessor try register it manually, helped in my case: services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>()
    • Luuk Wuijster
      Luuk Wuijster almost 6 years
      @Vitaly Nope, does not work :(
    • Code Name Jack
      Code Name Jack almost 6 years
      Did you try injecting HttpContextAccessor to you constructor? Also HttpContextAccessor has to be registered manually.
    • Luuk Wuijster
      Luuk Wuijster almost 6 years
      What do you mean by that?
    • Vitaly
      Vitaly almost 6 years
      I can't check right now, but just to test, can you try using IActionContextAccessor instead? Register like this: services.AddSingleton<IActionContextAccessor, ActionContextAccessor>(), then change your code to _services.GetRequiredService<IActionContextAccessor>().Actio‌​nContext.HttpContext‌​.User
    • gsharp
      gsharp almost 6 years
      I have the same issue. It doesn't seem to be related to IHttpContextAccessor, but to somethihng else.
    • Code Name Jack
      Code Name Jack almost 6 years
      AppContractResolver(IServiceProvider services, IHttpContextAccessor httpcontextaccessor) { _services = services; this.httpContextAccessor =httpcontextaccessor; } And in RegisterServices in Startup.cs add, services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    • Luuk Wuijster
      Luuk Wuijster almost 6 years
      @CodeNameJack Hmmmmmm.... While this does work, I don't know if this is the right way of doing things...
    • Scott Chamberlain
      Scott Chamberlain almost 6 years
      Don't put your workaround in the question, post it as your own answer. And your "workaround" actually is the correct way to do this.
    • Luuk Wuijster
      Luuk Wuijster almost 6 years
      @ScottChamberlain Hmmmmm.... Okay, did not know this is the correcty way. I will first wait for CodeNameJack to post an answer because he came up with the answer. If he doesn't answer within like a day, I will post an answer.
    • Luuk Wuijster
      Luuk Wuijster almost 6 years
      @CodeNameJack See comment above
    • Scott Chamberlain
      Scott Chamberlain almost 6 years
      You should try to avoid passing in a IServiceProvider to your classes and instead pass in the actual thing you need to use. It solves some edge cases (like yours) and it makes it easier to see what your class is actually using for it's dependencies.
    • Scott Chamberlain
      Scott Chamberlain almost 6 years
      @LuukWuijster also a helpful tip, any time you need to "delay" the resolve or resolve it multiple times you can pass in a Func<YourTypeHere> yourTypeFactory to your function and calling a var foo = yourTypeFactory() is exactly the same as doing var foo = serviceprovider.Resolve<YourTypeHere>()
    • Luuk Wuijster
      Luuk Wuijster almost 6 years
      @ScottChamberlain Oh okay, I didn't know that. That can be really helpful. Thanks!
  • Matan Shahar
    Matan Shahar almost 6 years
    IServiceProvider is registered by the framework. It's the container itself
  • Scott Chamberlain
    Scott Chamberlain almost 6 years
    @MatanShahar just a FYI the answer was updated and now contains correct info.
  • Anderson Paiva
    Anderson Paiva almost 6 years
    Thanks, I have a ServiceLocator and I could make this Change: private static IServiceProvider _provider; public static void Init(IServiceProvider provider) { _provider = provider; } public static T Resolve<T>() => (T)_provider.GetService(typeof(T)); "To:" private static IApplicationBuilder _app; public static void Init(IApplicationBuilder app) { _app = app; } public static T Resolve<T>() => (T)_app.ApplicationServices.GetService(typeof(T));
  • Cheesi
    Cheesi about 5 years
    Any Github link to this issue?
  • jjxtra
    jjxtra almost 4 years
    Bug seems to be gone in .net core 3
  • timmi4sa
    timmi4sa about 3 years
    OMG: the app.ApplicationServices is the most amazing find! Thank you for the suggestion that saved me even more hours of continued research, trial and error.
  • Juan Pablo
    Juan Pablo over 2 years
    :'( I've spent worth time, but I've improved my patience : D thanks!
  • MTAG11
    MTAG11 over 2 years
    This was useful for me, I had the same thing happen in a controller method.