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.
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.
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