Hot Swapping Custom Configurations in ASP.NET Core Using IOptionsSnapshot

In a previous article we went over how to read custom configurations into memory in ASP.NET Core. This is also the new way to do Appsettings. But did you know that you can also do “hot loading” of configurations? That is, while your app is running, you can change an appsetting or configuration and your application will reload it on the fly without an app pool recycle or restarting the web server? Pretty nifty! Let’s take a look.

A couple of notes before we start :

  • We will be reusing our code from the custom configurations in ASP.NET Core tutorial. If you haven’t read that yet maybe take a quick read to make sure we are on the same page.
  • This only works in ASP.net core 1.1 and up. Before that there were a couple of hot loading options that made it into early versions but ended up being problematic and being removed. In earlier versions this was named IOptionsMonitor (Which is still there under the hood).

First, in your Startup.cs ensure that when you load your appSettings.json, that reloadOnChange is set to true. It should look something like this :

var builder = new ConfigurationBuilder()
	.SetBasePath(env.ContentRootPath)
	.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

When you load your configuration into your services collection, you now must load it as configuration as opposed to loading it as a POCO. That means it should look like this :

services.Configure<MyConfiguration>(Configuration.GetSection("myConfiguration"));

When you request it into your controller/service, you then need to use IOptionsSnapshot rather than IOptions.

private readonly MyConfiguration _myConfiguration;

public MyController(IOptionsSnapshot<MyConfiguration> myConfiguration)
{
	_myConfiguration = myConfiguration.Value;
}

And that’s all! Now whenever you change configuration, your configuration is reloaded and your changes are seen instantly without a large restart required. This would be handy if you were deploying a prototype or a new feature that you’re unsure of how it would perform and need a way to tune it or disable the feature all together without requiring wholesale restarts.

Important. It’s A Snapshot!

It should be noted that the name IOptionsSnapshot is as the name implies, it’s a snapshot. If you for example take the value and hold onto that for some reason (In your own cache for example), these will not be hot loaded when changing configuration. Instead each time IOptionsSnapshot is injected into a class it will be given it’s unique value. This is very important to remember. Consider the following code :

private readonly IOptionsSnapshot<MyConfiguration> _myConfiguration;

public MyController(IOptionsSnapshot<MyConfiguration> myConfiguration)
{
	_myConfiguration = myConfiguration;
}

[HttpGet("")]
public bool Get()
{
	var first = _myConfiguration.Value.MyProperty;
	var second = _myConfiguration.Value.MyProperty;
	return second;
}

Where the configuration value of MyProperty is a boolean. If between the first and second calls to the value of MyProperty, I go into the configuration and change the value. What do you think this action will return? The answer is true as IOptionsSnapshot only reads the configuration when being created, not when you request the value from it.

In our example here, we are using an MVC controller which is Transient scope. Meaning that each time we request the controller, our DI recreates it for us. But it’s important to remember that if you are using something with a Singleton scope (Or to some extent a “scoped” scope), and injecting IOptionsSnapshot into that, the options will never be updated.

2 thoughts on “Hot Swapping Custom Configurations in ASP.NET Core Using IOptionsSnapshot”

  1. How could i acess IOptionsSnapshot by a class?
    I also have to add it for example in Constructor… Than its needed if i create an object to pass the IOptionSnapshot to the Object. But in Controller its not needed – i gets the value automatically.

    Reply
    • You should make your class also be injectable. So you inject first the class into the constructor, and then inject the IOptionsSnapshot object into your class.

      Reply

Leave a Comment