Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot use IOptionsMonitor to detect changes in ASP.NET Core

I am working on Asp.Net Core app

I want to change the configuration settings after running the application

I am using IOptionsMonitor, but it is not detecting changes

In Startup.cs -> Configuration() method I have

services.Configure<Config>(Configuration.GetSection("someConfig"));

In a different class where these config settings are read, I wrote something like

var someConfig= serviceProvider.GetRequiredService<IOptionsMonitor<Config>>();

But when I change the configuration file (Json File), the change is not detected, and someConfig does not change.

Config POCO class:

public class Config
{
    public string name {get; set;}
    //More getters and setters
}

Edit:

services.AddSingleton<ConfigHelpers>;

I am using a singleton object in which I am trying to read the config. It works fine if its not a snigleton. Is there a way to change the config even in a singleton object ?

in ConfigHelpers.cs

var someConfig= serviceProvider.GetRequiredService<IOptionsMonitor<Config>();

since it is defined as singleton in Startup.cs, changes made to Config are not reflected.

like image 534
PHPMODE Avatar asked Mar 23 '18 16:03

PHPMODE


2 Answers

Did you create your WebHostBuilder like this aprox:

var config = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("config.json", optional: false, reloadOnChange: true)
    .AddEnvironmentVariables()
    .Build();

var AppConfig = config.Get<AppConfig>();

var host = new WebHostBuilder()
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseUrls("http://*:" + (AppConfig.Port ?? 80))
    .UseKestrel()
    .UseIISIntegration()
    // Clones your config values
    .UseConfiguration(config)
    .UseStartup<Startup>()
    .Build();

Then it will clone your values and you'll loose the live reload ability.

You'll have to use ConfigureAppConfiguration and do the following:

var host = new WebHostBuilder()
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseUrls("http://*:" + (AppConfig.Port ?? 80))
    .UseKestrel()
    .ConfigureAppConfiguration((builder, conf) =>
    {
        conf.SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("config.json", optional: false, reloadOnChange: true)
            .AddEnvironmentVariables();
    })
    .UseIISIntegration()
    //.UseConfiguration(config)
    .UseStartup<Startup>()
    .Build();
like image 139
Bjorn Bailleul Avatar answered Sep 25 '22 15:09

Bjorn Bailleul


After a long day with .NET Core 3.1 reading the docs, various blog and forum posts and implementing all the suggested variations of IOptionsMonitor, IOptions, IOptionsSnapshot, IConfiguration, IServiceCollection and IServiceProvider, the only way I could get a dynamic update to work with the JsonConfigurationProvider (appsettings.json) and ConfigureWebHostDefaults() was this rather ugly workaround that could be implemented in a singleton as per the question:

    /// <summary>
    /// Reference to the application IConfiguration implementation
    /// </summary>
    static IConfiguration configuration;

    /// <summary>
    /// Reference buffer for Configuration property
    /// </summary>
    static AppConfiguration appConfiguration = new AppConfiguration();

    /// <summary>
    /// Access to the current configuration
    /// </summary>
    public static AppConfiguration Configuration
    {
        get
        {
                configuration.Bind("AppConfiguration", appConfiguration);
                return appConfiguration;
        }
    }
like image 42
noontz Avatar answered Sep 24 '22 15:09

noontz