weixin_39972768
weixin_39972768
2020-12-27 08:00

appsettings does not get reloaded when using UseConfiguration extension method

The appsettings.json file is never reloaded on change when using the UseConfiguration extension method.

 csharp
public static IWebHost DoesntWork(string[] args)
{
    var config = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appSettings.json", optional: false, reloadOnChange: true)
        .Build();

    return new WebHostBuilder()
        .UseKestrel()
        .UseConfiguration(config)
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseStartup<startup>()
        .Build();
}
</startup>

Using the ConfigureAppConfiguration extension method however does cause the appsettings.json file to be reloaded on change.

 csharp
public static IWebHost Works(string[] args)
{
    return new WebHostBuilder()
        .UseKestrel()
        .ConfigureAppConfiguration((builder, config) =>
        {
            config.AddJsonFile("appSettings.json", optional: false, reloadOnChange: true);
        })
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseStartup<startup>()
        .Build();
}
</startup>

I've created a sample project that uses a feature toggle to optionally print "Hello World" on the home page. Example project: https://github.com/BennieCopeland/AppSettingBug

该提问来源于开源项目:aspnet/Hosting

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

6条回答

  • weixin_39528843 weixin_39528843 4月前

    That's expected. UseConfiguration copies all of the keys: https://github.com/aspnet/Hosting/blob/a63932a492513cdeb4935661145084cad2ae5521/src/Microsoft.AspNetCore.Hosting.Abstractions/HostingAbstractionsWebHostBuilderExtensions.cs#L24-L32

    It would be nice to change this behavior in 3.0.

    点赞 评论 复制链接分享
  • weixin_39972768 weixin_39972768 4月前

    Is there documentation on the difference between host and application configuration? While I like the changes that took place with 2.0, it kind of muddied the waters when figuring out configuration. And this:

     csharp
        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<startup>()
                .Build();
    </startup>

    hides a lot of the magic. It's not clear on if I can override settings by just adding UseKestrel(options => {...}), so I went back to the long way of using WebHostBuilder and ran into my issue above.

    It seems that there are now at least two configurations, a Host UseConfiguration and Application ConfigureAppConfiguration, which is fine, but the documentation could be clearer. The IOptionsSnapshot page talks about the hot reloading, but doesn't say how to enable it. The Configuration page, talks all about configuration, and file formats, and custom providers; but all the examples use the ConfigurationBuilder and don't show how it plugs into ASP.Net Core. The Hosting page talks about UserConfiguration, but ConfigureAppConfiguration isn't even documented. It shows up in a code example on the Startup page, but is never explained.

    点赞 评论 复制链接分享
  • weixin_39528843 weixin_39528843 4月前

    https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/web-host?view=aspnetcore-2.1&tabs=aspnetcore2x is the doc where this should go. Please comment there.

    点赞 评论 复制链接分享
  • weixin_39658900 weixin_39658900 4月前

    I've been trying to solve this issue as well as far as I can tell when using .AddJsonFile("appSettings.json", optional: false, reloadOnChange: true) this won't rigger an "OnChange" event when configuration is changed during runtime due to a condition in FileConfigurationProvider

    csharp
    public FileConfigurationProvider(FileConfigurationSource source)
            {
                if (source == null)
                {
                    throw new ArgumentNullException(nameof(source));
                }
                Source = source;
    
                if (Source.ReloadOnChange && Source.FileProvider != null)
                {
                    ChangeToken.OnChange(
                        () => Source.FileProvider.Watch(Source.Path),
                        () => {
                            Thread.Sleep(Source.ReloadDelay);
                            Load(reload: true);
                        });
                }
    }
    

    Take note of the if (Source.ReloadOnChange && Source.FileProvider != null) When calling AddJsonFile this sets he FileProvider to null so this condition is never true. I've tried trawling the source to see if the FileProfile for JsonSource is configured elsewhere or I might be miss understanding it completely.

    .....

    Having said that while writing this comment and looking at the source i found

    csharp
    namespace Microsoft.Extensions.Configuration.Json
    {
        /// <summary>
        /// Represents a JSON file as an <see cref="IConfigurationSource"></see>.
        /// </summary>
        public class JsonConfigurationSource : FileConfigurationSource
        {
            /// <summary>
            /// Builds the <see cref="JsonConfigurationProvider"></see> for this source.
            /// </summary>
            /// <param name="builder">The <see cref="IConfigurationBuilder"></see>.
            /// <returns>A <see cref="JsonConfigurationProvider"></see></returns>
            public override IConfigurationProvider Build(IConfigurationBuilder builder)
            {
                EnsureDefaults(builder);
                return new JsonConfigurationProvider(this);
            }
        }
    }
    

    Which calls EnsureDefaults which looks like this is where the FileProvider will be setup. Using PhysicalFileProvider

    Still - I cannot get file changes to work successfully :(

    点赞 评论 复制链接分享
  • weixin_39528843 weixin_39528843 4月前

    That is not related to hosting or this issue. Please open a new issue against configuration.

    点赞 评论 复制链接分享
  • weixin_39528843 weixin_39528843 4月前

    There's not a good way to fix UseConfiguration since it's an extension method on IWebHostBuilder which only has GetSetting and UseSetting and we're trying to avoid breaking the interface.

    This isn't an issue going forward because generic host has ConfigureHostConfiguration with first class config support.

    点赞 评论 复制链接分享

相关推荐