• Home

  • Custom Ecommerce
  • Application Development
  • Database Consulting
  • Cloud Hosting
  • Systems Integration
  • Legacy Business Systems
  • Security & Compliance
  • GIS

  • Expertise

  • About Us
  • Our Team
  • Clients
  • Blog
  • Careers

  • VisionPort

  • Contact
  • Our Blog

    Ongoing observations by End Point Dev people

    Monitoring Settings Changes in ASP.NET Core

    Daniel Gomm

    By Daniel Gomm
    September 22, 2021

    Ripples in water
    Photo by Linus Nylund on Unsplash

    Did you know you can directly respond to config file changes in ASP.NET Core? By using the IOptionsMonitor<T> interface, it’s possible to run a lambda function every time a config file is updated.

    For those who aren’t too familiar with it, ASP.NET Core configuration is handled using the Options Pattern. That is, you create a model class that has a field for each property in your config file, and then set up the application to map the configuration to that class, which can be injected into controllers and services. In your controllers, you can request the configuration class T as a dependency by using an options wrapper class like IOptions<T>.

    While this works just fine in some cases, it doesn’t allow you to actually run code when the configuration is changed. However, if you request your configuration using IOptionsMonitor<T>, you get the ability to define a lambda function to run every time appsettings.json is changed.

    One use case for this functionality would be if you wanted to maintain a list in the config file, and log every time that list was changed. In this article I’ll explain how to set up an ASP.NET Core 5.0 API to run custom code whenever changes are made to appsettings.json.

    Setting up the API

    In order to use the options pattern in your API, you’ll first need to add the options services to the container using the services.AddOptions() method. Then, you can register your custom configuration class (in this example, MyOptions) to be bound to a specific section in appsettings.json (in this example, "myOptions").

    public void ConfigureServices(IServiceCollection services)
    {
      // ...
    
      // Add options services to the container
      services.AddOptions();
    
      // Configure the app to map the "myOptions" section of
      // the config file to the MyOptions model class
      services.Configure<MyOptions>(
        Configuration.GetSection("myOptions")
      );
    }
    

    Monitoring Configuration Changes

    Now that the API is set up correctly, in your controllers you can directly request the configuration using IOptionsMonitor<T>. You can also unpack the configuration instance itself by using the IOptionsMonitor<T>.CurrentValue property. This value will automatically get updated by IOptionsMonitor<T> when the configuration is changed, so you only need to retrieve it once in the constructor.

    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Options;
    
    [Route("api/[controller]")]
    [ApiController]
    public class MyController : ControllerBase
    {
      private MyOptions MyOptions;
    
      public MyController(IOptionsMonitor<MyOptions> MyOptionsMonitor)
      {
        // Stores the actual configuration in the controller
        // to reference later. Changes to the config will be
        // reflected in MyOptions.
        this.MyOptions = MyOptionsMonitor.CurrentValue;
    
        // Registers a lambda function to be called every time
        // a configuration change is made
        MyOptionsMonitor.OnChange(async (opts) =>
        {
          // Write some code!
        });
      }
    }
    

    One small gotcha worth noting is that the OnChange function isn’t debounced. So if you’re using an IDE that automatically saves as you type, it’ll trigger the OnChange function rapidly as you edit appsettings.json.

    Conclusion

    And that’s it! It doesn’t take much to get your API to run custom code on config file changes.

    Have any questions? Feel free to leave a comment!

    monitoring dotnet aspdotnet


    Comments