Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
like image 698
Luuk Wuijster Avatar asked May 31 '18 08:05

Luuk Wuijster


People also ask

Why IServiceProvider is disposed?

If you have a transient service constructor that takes an IServiceProvider, the service provider will be disposed. This is a bug in . NET core. Work-around is to manage your own transient life-cycle in a pooling class.

What is IServiceProvider .NET core?

The IServiceProvider is responsible for resolving instances of types at runtime, as required by the application. These instances can be injected into other services resolved from the same dependency injection container. The ServiceProvider ensures that resolved services live for the expected lifetime.

What does Cannot access a disposed object mean?

: '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.

What is disposed object in C#?

In the context of C#, dispose is an object method invoked to execute code required for memory cleanup and release and reset unmanaged resources, such as file handles and database connections.


6 Answers

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

like image 87
Denis Olifer Avatar answered Oct 03 '22 18:10

Denis Olifer


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

like image 36
Code Name Jack Avatar answered Oct 03 '22 20:10

Code Name Jack


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.

like image 22
jjxtra Avatar answered Oct 03 '22 18:10

jjxtra


For me it works with:

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

and then:

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

     ...

    }
like image 33
user3198116 Avatar answered Oct 03 '22 19:10

user3198116


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
like image 24
Greg Gum Avatar answered Oct 03 '22 18:10

Greg Gum


In my case I didn't have the async await on the rest API method, so it was disposing the IServiceProvider before the end of the call.

like image 1
Daniel Lobo Avatar answered Oct 03 '22 18:10

Daniel Lobo