Reloading Options with reloadOnChange in ASP.NET Core


Reloading Options with reloadOnChange in ASP.NET Core



In my ASP.NET Core application I bind the appsettings.json to a strongly typed class AppSettings.


public Startup(IHostingEnvironment environment)
{
var builder = new ConfigurationBuilder()
.SetBasePath(environment.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{environment.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();

Configuration = builder.Build();
}

public void ConfigureServices(IServiceCollection services)
{
services.Configure<AppSettings>(Configuration);
//...
}



In a singleton class I wrap this AppSettings class like this:


public class AppSettingsWrapper : IAppSettingsWrapper
{
private readonly IOptions<AppSettings> _options;

public AppSettingsAdapter(IOptions<AppSettings> options)
{
_options = options ?? throw new ArgumentNullException("Options cannot be null");
}

public SomeObject SomeConvenienceGetter()
{
//...
}
}



Now I'm struggling with reloading the AppSettings if the json file changes. I read somewhere that the class IOptionsMonitor can detect changes but it doesn't work in my case.



I tried calling the OnChange event like this for testing purposes:


public void Configure(IApplicationBuilder applicationBuilder, IOptionsMonitor<AppSettings> optionsMonitor)
{
applicationBuilder.UseStaticFiles();
applicationBuilder.UseMvc();

optionsMonitor.OnChange<AppSettings>(vals =>
{
System.Diagnostics.Debug.WriteLine(vals);
});
}



The event is never triggered when I change the json file. Has someone an idea what I can change to get the reloading mechanic to work in my scenario?




1 Answer
1



You need to inject IOptionsSnapshot<AppSettings> to get the reload working.


IOptionsSnapshot<AppSettings>



Unfortunately you cannot load the IOptionsSnapshot into a Singleton service. IOptionsSnapshot is a Scoped service so you can only reference it in a Scoped or Transient registered class.


IOptionsSnapshot


IOptionsSnapshot



But, if think about it, that makes sense. The settings need to be reloaded when they change so if you inject them into a Singleton then the class will never get the updated settings because the constructor will not be called again for a Singleton.





I thought that I maybe could rebind the AppSettingsWrapper with the new AppSettings in the "OnChange" event. It is unfortunate that I have to change the lifetime of my wrapper class because besides the rare reloading it never changes.
– Shamshiel
Jun 29 at 11:44





Unless you have a really compelling reason to keep it as a singleton e.g. real time performance, switching to a Scoped service should give you what you want without much penalty, after all you are still injecting the same class, only the registration has changed.
– Simply Ged
Jun 29 at 13:15


Scoped






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Comments

Popular posts from this blog

paramiko-expect timeout is happening after executing the command

how to run turtle graphics in Colaboratory

Export result set on Dbeaver to CSV