From 27c24a81435836e3cdd948b7a019e952ca2d7987 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Wed, 22 Sep 2021 15:17:46 -0700 Subject: [PATCH] Add the ConfigurationManager to the IServiceCollection (#36832) - 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 f90fc5115060..595f5db980d3 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() {