diff --git a/src/Hosting/Hosting/src/Host.cs b/src/Hosting/Hosting/src/Host.cs index 5aeec52dc9b..f8d67e56d98 100644 --- a/src/Hosting/Hosting/src/Host.cs +++ b/src/Hosting/Hosting/src/Host.cs @@ -71,9 +71,11 @@ public static IHostBuilder CreateDefaultBuilder(string[] args) builder.ConfigureAppConfiguration((hostingContext, config) => { var env = hostingContext.HostingEnvironment; + + var reloadOnChange = hostingContext.Configuration.GetValue("hostBuilder:reloadConfigOnChange", defaultValue: true); - config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) - .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); + config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: reloadOnChange) + .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: reloadOnChange); if (env.IsDevelopment() && !string.IsNullOrEmpty(env.ApplicationName)) { diff --git a/src/Hosting/Hosting/test/HostTests.cs b/src/Hosting/Hosting/test/HostTests.cs index 9e1c27c9106..bfce74ac543 100644 --- a/src/Hosting/Hosting/test/HostTests.cs +++ b/src/Hosting/Hosting/test/HostTests.cs @@ -8,6 +8,8 @@ using System.Diagnostics.Tracing; using System.IO; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -82,6 +84,81 @@ public void CreateDefaultBuilder_EnablesValidateOnBuild() Assert.Throws(() => hostBuilder.Build()); } + [Fact] + public async Task CreateDefaultBuilder_ConfigJsonDoesNotReload() + { + var reloadFlagConfig = new Dictionary() {{ "hostbuilder:reloadConfigOnChange", "false" }}; + var appSettingsPath = Path.Combine(Path.GetTempPath(), "appsettings.json"); + + string SaveRandomConfig() + { + var newMessage = $"Hello ASP.NET Core: {Guid.NewGuid():N}"; + File.WriteAllText(appSettingsPath, $"{{ \"Hello\": \"{newMessage}\" }}"); + return newMessage; + } + + var dynamicConfigMessage1 = SaveRandomConfig(); + + var host = Host.CreateDefaultBuilder() + .UseContentRoot(Path.GetDirectoryName(appSettingsPath)) + .ConfigureHostConfiguration(builder => + { + builder.AddInMemoryCollection(reloadFlagConfig); + }) + .Build(); + + var config = host.Services.GetRequiredService(); + + Assert.Equal(dynamicConfigMessage1, config["Hello"]); + + var dynamicConfigMessage2 = SaveRandomConfig(); + await Task.Delay(1000); // Give reload time to fire if it's going to. + Assert.NotEqual(dynamicConfigMessage1, dynamicConfigMessage2); // Messages are different. + Assert.Equal(dynamicConfigMessage1, config["Hello"]); // Config did not reload + } + + [Fact] + public async Task CreateDefaultBuilder_ConfigJsonDoesReload() + { + var reloadFlagConfig = new Dictionary() { { "hostbuilder:reloadConfigOnChange", "true" } }; + var appSettingsPath = Path.Combine(Path.GetTempPath(), "appsettings.json"); + + string SaveRandomConfig() + { + var newMessage = $"Hello ASP.NET Core: {Guid.NewGuid():N}"; + File.WriteAllText(appSettingsPath, $"{{ \"Hello\": \"{newMessage}\" }}"); + return newMessage; + } + + var dynamicConfigMessage1 = SaveRandomConfig(); + + var host = Host.CreateDefaultBuilder() + .UseContentRoot(Path.GetDirectoryName(appSettingsPath)) + .ConfigureHostConfiguration(builder => + { + builder.AddInMemoryCollection(reloadFlagConfig); + }) + .Build(); + + var config = host.Services.GetRequiredService(); + + Assert.Equal(dynamicConfigMessage1, config["Hello"]); + + var dynamicConfigMessage2 = SaveRandomConfig(); + + var configReloadedCancelTokenSource = new CancellationTokenSource(); + var configReloadedCancelToken = configReloadedCancelTokenSource.Token; + + config.GetReloadToken().RegisterChangeCallback(o => + { + configReloadedCancelTokenSource.Cancel(); + }, null); + // Wait for up to 10 seconds, if config reloads at any time, cancel the wait. + await Task.WhenAny(Task.Delay(10000, configReloadedCancelToken)); // Task.WhenAny ignores the task throwing on cancellation. + Assert.NotEqual(dynamicConfigMessage1, dynamicConfigMessage2); // Messages are different. + Assert.Equal(dynamicConfigMessage2, config["Hello"]); // Config DID reload from disk + } + internal class ServiceA { } internal class ServiceB