Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

DI doesn't work as expected in Development builds #6407

Closed
shawnwildermuth opened this issue Jun 18, 2017 · 4 comments
Closed

DI doesn't work as expected in Development builds #6407

shawnwildermuth opened this issue Jun 18, 2017 · 4 comments

Comments

@shawnwildermuth
Copy link

I have a service I want to register in Startup.ConfigureServices then inject into Startup.Configure but it fails in Development builds but not release builds. I'm using 2.0.0-preview-1 builds. I have a repro case attached. To reproduce:

  1. Open zip file into directory and open a cmd console
  2. type "dotnet run" and watch the home page appear
  3. Stop the service
  4. Add 'set ASPNETCORE_ENVIRONMENT=Development' in the console window
  5. type "dotnet run" and see the exception happen.

The exception is as follows in the development execution:

D:\working\TestDI>dotnet run

Unhandled Exception: System.Exception: Could not resolve a service of type 'TestDI.Services.MailService' for the parameter 'mailService' of method 'Configure' on type 'TestDI.Startup'. ---> System.InvalidOperationException: Cannot resolve scoped service 'TestDI.Services.MailService' from root provider.
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateResolution(Type serviceType, ServiceProvider serviceProvider)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.AspNetCore.Hosting.Internal.ConfigureBuilder.Invoke(Object instance, IApplicationBuilder builder)
   --- End of inner exception stack trace ---
   at Microsoft.AspNetCore.Hosting.Internal.ConfigureBuilder.Invoke(Object instance, IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.Internal.ConfigureBuilder.<>c__DisplayClass4_0.<Build>b__0(IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
   at Microsoft.AspNetCore.Hosting.Internal.AutoRequestServicesStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
   at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
   at TestDI.Program.BuildWebHost(String[] args) in D:\working\TestDI\Program.cs:line 21
   at TestDI.Program.Main(String[] args) in D:\working\TestDI\Program.cs:line 17

TestDI.zip

@davidfowl
Copy link
Member

In 2.0.0 the DI container is configured to help you not shoot yourself in the foot (but only in development because of fear of breaking people's running albeit probably buggy apps). Scoped dependencies shouldn't be injected directly into the Configure method, instead, you should create a scope and resolve your dependency from that scope:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<ScopedThing>();
    }

    public void Configure(IApplicationBuilder app)
    {
        using (var scope = app.ApplicationServices.CreateScope())
        {
            var scopedThing = scope.ServiceProvider.GetRequiredService<ScopedThing>();
        }
    }
}

@shawnwildermuth
Copy link
Author

I want to create it the default scope (e.g. the request scope), isn't this just doing the wrong thing? or is it just because I'm doing work in the Configure method that I need a scope (in Configure) since I am not in a request scope yet?

@shawnwildermuth
Copy link
Author

I get it now. Thanks @davidfowl!

@davidfowl
Copy link
Member

FWIW aspnet/Hosting#1106

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants