From 4d7fe9c04240fabda1a869741d60739cbe8e9278 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Tue, 21 Sep 2021 23:25:16 -0700 Subject: [PATCH] Add the ConfigurationManager to the IServiceCollection - Add an IConfiguration to the service collection for scenarios where uses end up prematurely building the service provider or sniffing the IServiceCollection for it. We then remove the ConfigurationManager reference it from the final IServiceCollection to avoid cycles in the configuration graph that result in stack overflows (we link the configuration manager to the final configuration that has been built). - Added tests --- .../src/WebApplicationBuilder.cs | 13 ++++++++ .../WebApplicationTests.cs | 33 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/DefaultBuilder/src/WebApplicationBuilder.cs b/src/DefaultBuilder/src/WebApplicationBuilder.cs index cf610fef4c4b..e7e6269d0205 100644 --- a/src/DefaultBuilder/src/WebApplicationBuilder.cs +++ b/src/DefaultBuilder/src/WebApplicationBuilder.cs @@ -99,6 +99,8 @@ internal WebApplicationBuilder(WebApplicationOptions options, Action(Configuration); } /// @@ -171,6 +173,17 @@ public WebApplication Build() // we called ConfigureWebHostDefaults on both the _deferredHostBuilder and _hostBuilder. foreach (var s in _services) { + // Skip the configuration manager instance we added earlier + // we're already going to wire it up to this new configuration source + // after we've built the application. There's a chance the user manually added + // this as well but we still need to remove it from the final configuration + // to avoid cycles in the configuration graph + if (s.ServiceType == typeof(IConfiguration) && + s.ImplementationInstance == Configuration) + { + continue; + } + services.Add(s); } diff --git a/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/WebApplicationTests.cs b/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/WebApplicationTests.cs index 672e9be73588..e475c00062ce 100644 --- a/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/WebApplicationTests.cs +++ b/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/WebApplicationTests.cs @@ -693,6 +693,39 @@ public async Task WebApplicationConfiguration_HostFilterOptionsAreReloadable() Assert.Contains("NewHost", options.AllowedHosts); } + [Fact] + public void CanResolveIConfigurationBeforeBuildingApplication() + { + var builder = WebApplication.CreateBuilder(); + var sp = builder.Services.BuildServiceProvider(); + + var config = sp.GetService(); + Assert.NotNull(config); + Assert.Same(config, builder.Configuration); + + var app = builder.Build(); + + // These are different + Assert.NotSame(app.Configuration, builder.Configuration); + } + + [Fact] + public void ManuallyAddingConfigurationAsServiceWorks() + { + var builder = WebApplication.CreateBuilder(); + builder.Services.AddSingleton(builder.Configuration); + var sp = builder.Services.BuildServiceProvider(); + + var config = sp.GetService(); + Assert.NotNull(config); + Assert.Same(config, builder.Configuration); + + var app = builder.Build(); + + // These are different + Assert.NotSame(app.Configuration, builder.Configuration); + } + [Fact] public async Task WebApplicationConfiguration_EnablesForwardedHeadersFromConfig() {