You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Function worker's service provider resolves scoped service from the root as singleton #97091
Framework version: .Net 8.0
Package causing the problem: Microsoft.Azure.Functions.Worker, v1.20.1
Description
In ASP Core web application runtime, trying to resolve a scoped service from a non-scoped (root) service provider throws an error with the following message:
Cannot resolve scoped service from root provider
However, using an instance of IHost built by HostBuilder from Microsoft.Extensions.Hosting doesn't seem to respect service lifetime registration. This can be easily reproduced with the below code. It seems like a bug because the service resolution behavior isn't consistent and can lead to tricky bugs with dependencies relying on scoped context.
Expected behavior
An exception is thrown when resolving a scoped service from a root provider.
usingMicrosoft.Extensions.DependencyInjection;usingMicrosoft.Extensions.Hosting;varbuilder=newHostBuilder().ConfigureFunctionsWorkerDefaults();builder.ConfigureServices((_,services)=>services.AddScoped<IDependency,DependencyImplementation>());varhost=builder.Build();vardepOne=host.Services.GetRequiredService<IDependency>();// Expected to get exception here but it resolved the servicevardepTwo=host.Services.GetRequiredService<IDependency>();varareEqual=depOne==depTwo;// true, received same instancevarscopedDepOne=host.Services.CreateScope().ServiceProvider.GetRequiredService<IDependency>();varscopedDepTwo=host.Services.CreateScope().ServiceProvider.GetRequiredService<IDependency>();areEqual=scopedDepOne==scopedDepTwo;// false, received scoped instances as expectedConsole.ReadKey();interfaceIDependency{}classDependencyImplementation:IDependency{}
Thanks for your response, @wcsanders1. However- apologies if it's slightly off topic- isn't this a symptom of a rather wider problem stemming from the design of the DI's default behaviour? Given that scope validation is not enabled by default, it's possible to run into a tricky and potentially dangerous scenario, i.e. resolving a singleton service that takes in a scoped dependency.
varservices=newServiceCollection();services.AddSingleton<ISingletonDependency,SingletonDependencyImplementation>().AddScoped<IScopedDependency,ScopedDependencyImplementation>();varprovider=services.BuildServiceProvider().CreateScope().ServiceProvider;varsingleton=provider.GetRequiredService<ISingletonDependency>();// Resolves successfully with an injected scoped dependencyclassSingletonDependencyImplementation:ISingletonDependency{// This should never happenpublicSingletonDependencyImplementation(IScopedDependencyscoped){// ...}}
Activity
wcsanders1 commentedon Feb 27, 2024
@aventus13 It looks like this failure to validate the scope is a result of calling the
HostBuilderconstructor rather than theCreateDefaultBuildermethod, which enables scope validation when the environment isDevelopment: https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs#L327aventus13 commentedon Feb 27, 2024
Thanks for your response, @wcsanders1. However- apologies if it's slightly off topic- isn't this a symptom of a rather wider problem stemming from the design of the DI's default behaviour? Given that scope validation is not enabled by default, it's possible to run into a tricky and potentially dangerous scenario, i.e. resolving a singleton service that takes in a scoped dependency.
wcsanders1 commentedon Feb 28, 2024
I agree @aventus13 that it seems like such behavior would never be wanted. I plan to submit a PR to fix it within this week.
wcsanders1 commentedon Mar 3, 2024
I think #99199 should resolve this.
steveharter commentedon Mar 28, 2024
Yes thanks. This is a common issue; work done here to prevent scoped services from being used with a singleton constructor is good as long as it doesn't significantly affect perf in non-development runtime scenarios. As mentioned above, we do try to do error checking but only in development mode: https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs#L330-L331
buyaa-n commentedon Jul 26, 2024
Closing