.Net Core 2.1 - Cannot access a disposed object.Object name: 'IServiceProvider'
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
Related videos on Youtube
Comments
-
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 almost 6 yearsjust wanting to check, are you registering it in the .net core 2.1 way of calling
services.AddHttpContextAccessor();
-
Luuk Wuijster almost 6 yearsI have tried adding it, but did not work. Still got the same error
-
Vitaly almost 6 yearsInstead calling AddHttpContextAccessor try register it manually, helped in my case: services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>()
-
Luuk Wuijster almost 6 years@Vitaly Nope, does not work :(
-
Code Name Jack almost 6 yearsDid you try injecting HttpContextAccessor to you constructor? Also HttpContextAccessor has to be registered manually.
-
Luuk Wuijster almost 6 yearsWhat do you mean by that?
-
Vitaly almost 6 yearsI 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>().ActionContext.HttpContext.User
-
gsharp almost 6 yearsI have the same issue. It doesn't seem to be related to IHttpContextAccessor, but to somethihng else.
-
Code Name Jack almost 6 yearsAppContractResolver(IServiceProvider services, IHttpContextAccessor httpcontextaccessor) { _services = services; this.httpContextAccessor =httpcontextaccessor; } And in RegisterServices in Startup.cs add, services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
-
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 almost 6 yearsDon'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 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 almost 6 years@CodeNameJack See comment above
-
Scott Chamberlain almost 6 yearsYou 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 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 avar foo = yourTypeFactory()
is exactly the same as doingvar foo = serviceprovider.Resolve<YourTypeHere>()
-
Luuk Wuijster almost 6 years@ScottChamberlain Oh okay, I didn't know that. That can be really helpful. Thanks!
-
Matan Shahar almost 6 years
IServiceProvider
is registered by the framework. It's the container itself -
Scott Chamberlain almost 6 years@MatanShahar just a FYI the answer was updated and now contains correct info.
-
Anderson Paiva almost 6 yearsThanks, 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 about 5 yearsAny Github link to this issue?
-
jjxtra almost 4 yearsBug seems to be gone in .net core 3
-
timmi4sa about 3 yearsOMG: 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 over 2 years:'( I've spent worth time, but I've improved my patience : D thanks!
-
MTAG11 over 2 yearsThis was useful for me, I had the same thing happen in a controller method.