Bernard
Bernard

Reputation: 1015

Dependency injection within ASP.Net Core

Been doing some sample code with ASP.NET Core to try to understand how it fits together and I am stumped as to why I am unable to successfully resolve a service.

The configure services method has the call to add ISeedDataService

public void ConfigureServices(IServiceCollection services)
{
    services.AddOptions();
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    services.AddDbContext<CustomerDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddScoped<ICustomerDbContext, CustomerDbContext>();
    services.AddScoped<ICustomerRepository, CustomerRepository>();
    services.AddScoped<ISeedDataService, SeedDataService>();
}

In Configure I am calling AddSeedData() as below

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
   app.AddSeedData();
}

which is calling the extension method below

public static async void AddSeedData(this IApplicationBuilder app)
{
    var seedDataService = app.ApplicationServices.GetRequiredService<ISeedDataService>();
    await seedDataService.EnsureSeedData();
}

and the SeedDataService is below

public class SeedDataService : ISeedDataService
{
    private ICustomerDbContext _context;
    public SeedDataService(ICustomerDbContext context)
    {
        _context = context;
    }

    public async Task EnsureSeedData()
    {
        _context.Database.EnsureCreated();

        _context.Customers.RemoveRange(_context.Customers);
        _context.SaveChanges();

        Customer customer = new Customer();
        customer.FirstName = "Chuck";
        customer.LastName = "Norris";
        customer.Age = 30;
        customer.Id = Guid.NewGuid();

        _context.Add(customer);

        Customer customer2 = new Customer();
        customer2.FirstName = "Fabian";
        customer2.LastName = "Gosebrink";
        customer2.Age = 31;
        customer2.Id = Guid.NewGuid();

        _context.Add(customer2);

        await _context.SaveChangesAsync();
    }
}

Totally unsure as to what I am doing wrong, the error is System.InvalidOperationException: 'Cannot resolve scoped service 'secondapp.Services.ISeedDataService' from root provider.'

Upvotes: 1

Views: 610

Answers (2)

Brad
Brad

Reputation: 4553

The Configure() method allows parameter dependency injection so you can do the following.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ISeedDataService seedService)
{
    seedService.EnsureSeedData().Wait(); // Configure() is not async so you have to wait
}

Upvotes: -1

Henk Mollema
Henk Mollema

Reputation: 46651

You are (and should be) adding the ISeedDataService as scoped service. However, you are attempting to resolve it from the root service provider (e.g. app.ApplicationServices) which is not scoped. This means that scoped services resolved from it effectively are turned into a singleton service and are not disposed until the application shuts down or it will result in an error.

The solution here is to create a scope yourself:

public void Configure(IApplicationBuilder app)
{
    using (var scope = app.ApplicationServices.CreateScope())
    {
        var seedDataService = scope.ServiceProvider.GetRequiredService<ISeedDataService>();
        // Use seedDataService here
    }
}

Please take a look at the documentation regarding dependency injection scopes.


On a second note: your AddSeedData extension method is async void and you are not waiting for the result. You should return a task (async Task) call AddSeedData().GetAwaiter().GetResult() to make sure you block until the seeding is complete.

Upvotes: 3

Related Questions