Skip to content

Commit ce73350

Browse files
authored
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
1 parent 7700810 commit ce73350

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

src/DefaultBuilder/src/WebApplicationBuilder.cs

+13
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ internal WebApplicationBuilder(WebApplicationOptions options, Action<IHostBuilde
9999
Logging = new LoggingBuilder(Services);
100100
Host = new ConfigureHostBuilder(hostContext, Configuration, Services);
101101
WebHost = new ConfigureWebHostBuilder(webHostContext, Configuration, Services);
102+
103+
Services.AddSingleton<IConfiguration>(Configuration);
102104
}
103105

104106
/// <summary>
@@ -171,6 +173,17 @@ public WebApplication Build()
171173
// we called ConfigureWebHostDefaults on both the _deferredHostBuilder and _hostBuilder.
172174
foreach (var s in _services)
173175
{
176+
// Skip the configuration manager instance we added earlier
177+
// we're already going to wire it up to this new configuration source
178+
// after we've built the application. There's a chance the user manually added
179+
// this as well but we still need to remove it from the final configuration
180+
// to avoid cycles in the configuration graph
181+
if (s.ServiceType == typeof(IConfiguration) &&
182+
s.ImplementationInstance == Configuration)
183+
{
184+
continue;
185+
}
186+
174187
services.Add(s);
175188
}
176189

src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/WebApplicationTests.cs

+33
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,39 @@ public async Task WebApplicationConfiguration_HostFilterOptionsAreReloadable()
693693
Assert.Contains("NewHost", options.AllowedHosts);
694694
}
695695

696+
[Fact]
697+
public void CanResolveIConfigurationBeforeBuildingApplication()
698+
{
699+
var builder = WebApplication.CreateBuilder();
700+
var sp = builder.Services.BuildServiceProvider();
701+
702+
var config = sp.GetService<IConfiguration>();
703+
Assert.NotNull(config);
704+
Assert.Same(config, builder.Configuration);
705+
706+
var app = builder.Build();
707+
708+
// These are different
709+
Assert.NotSame(app.Configuration, builder.Configuration);
710+
}
711+
712+
[Fact]
713+
public void ManuallyAddingConfigurationAsServiceWorks()
714+
{
715+
var builder = WebApplication.CreateBuilder();
716+
builder.Services.AddSingleton<IConfiguration>(builder.Configuration);
717+
var sp = builder.Services.BuildServiceProvider();
718+
719+
var config = sp.GetService<IConfiguration>();
720+
Assert.NotNull(config);
721+
Assert.Same(config, builder.Configuration);
722+
723+
var app = builder.Build();
724+
725+
// These are different
726+
Assert.NotSame(app.Configuration, builder.Configuration);
727+
}
728+
696729
[Fact]
697730
public async Task WebApplicationConfiguration_EnablesForwardedHeadersFromConfig()
698731
{

0 commit comments

Comments
 (0)