On an ASP.NET Core project I have the following on Startup:
services.AddDbContext<Context>(x => x.UseSqlServer(connectionString)); services.AddTransient<IValidationService, ValidationService>(); services.AddTransient<IValidator<Model>, ModelValidator>();
The ValidationService is as follows:
public interface IValidationService { Task<List<Error>> ValidateAsync<T>(T model); } public class ValidationService : IValidationService { private readonly IServiceProvider _provider; public ValidationService(IServiceProvider provider) { _provider = provider; } public async Task<List<Error>> ValidateAsync<T>(T model) { IValidator<T> validator = _provider.GetRequiredService<IValidator<T>>(); return await validator.ValidateAsync(model); } }
And the ModelValidator is as follows:
public class ModelValidator : AbstractValidator<Model> { public ModelValidator(Context context) { // Some code using context } }
When I inject a IValidationService in a controller and use it as:
List<Error> errors = await _validator.ValidateAsync(order);
I get the error:
System.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: 'Context'.
Any idea why I am having this error when using Context inside ModelValidator.
How to fix this?
UPDATE
So I changed the code to:
services.AddScoped<IValidationService, ValidationService>(); services.AddScoped<IValidator<Model>, ModelValidator>();
But I get the same error ...
UPDATE - Seed Data Code inside Configure method on Startup
So on Configure method I have:
if (hostingEnvironment.IsDevelopment()) applicationBuilder.SeedData();
And the SeedData extension is:
public static class DataSeedExtensions { private static IServiceProvider _provider; public static void SeedData(this IApplicationBuilder builder) { _provider = builder.ApplicationServices; _type = type; using (Context context = (Context)_provider.GetService<Context>()) { await context.Database.MigrateAsync(); // Insert data code } }
What am I missing?
UPDATE - A possible solution
Changing my Seed method to the following seems to work:
using (IServiceScope scope = _provider.GetRequiredService<IServiceScopeFactory>().CreateScope()) { Context context = _provider.GetService<Context>(); // Insert data in database }
EF and EF Core DbContext types implement IDisposable . As such, best practice programming suggests that you should wrap them in a using() block (or new C# 8 using statement). Unfortunately, doing this, at least in web apps, is generally a bad idea.
This example registers a DbContext subclass called ApplicationDbContext as a scoped service in the ASP.NET Core application service provider (a.k.a. the dependency injection container). The context is configured to use the SQL Server database provider and will read the connection string from ASP.NET Core configuration.
Just a guess in what causes your error:
You are using DI and async calls. If, somewhere in your call stack, you return a void instead of Task, you get the described behavior. At that point, the call is ended and the context disposed. So check if you have an async call that returns a void instead of Task. If you change the return value, the ObjectDisposedException is probably fixed.
public static class DataSeedExtensions { private static IServiceProvider _provider; public static async Task SeedData(this IApplicationBuilder builder) { //This line of code _provider = builder.ApplicationServices; _type = type; using (Context context = (Context)_provider.GetService<Context>()) { await context.Database.MigrateAsync(); // Insert data code } }
And in configure:
if (hostingEnvironment.IsDevelopment()){ await applicationBuilder.SeedData(); }
Blog post on how to fix this error: Cannot access a disposed object in ASP.NET Core when injecting DbContext
I had a similar issue working with asp.net core. I have an async POST method in my controller and when it returns void I will have this exception. After I changed the POST method return a TASK the problem was solved.
Change from:
public async void PostAsync([FromBody] Model yourmodel)
To
public async Task PostAsync([FromBody] Model yourmodel)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With