Passing Configuration Options Into Middleware, Services and Controllers in ASP.NET Core 3.1

Full source code here.

I recently hit a problem where I needed to reload configuration settings as they changed, fortunately, this is relatively straightforward when using the IOptionsMonitor, in .NET Core.

Add a few lines to ConfigureServices, pass the configuration options as a scoped service to the controller or into another service and everything works.

Here is all you need in the ConfigureServices method -

1public void ConfigureServices(IServiceCollection services)
2{
3    services.AddOptions();
4    services.Configure<WeatherOptions>(Configuration.GetSection("WeatherOptions"));
5    services.AddScoped<ISomeService, SomeService>();

Here’s the service that takes the IOptionsMonitor -

1public class SomeService : ISomeService
2{
3    private readonly WeatherOptions _weatherOptions;
4
5    public SomeService(IOptionsMonitor<WeatherOptions> weatherOptions)
6    {
7        _weatherOptions = weatherOptions.CurrentValue;
8    }
9// snip..

And here is the controller taking the IOptionsMonitor and the service that also uses the options, this is of course contrived and you almost certainly would not want to take both constructor parameters -

1public class WeatherForecastController : ControllerBase
2{
3    private readonly WeatherOptions _weatherOptions;
4    private readonly ISomeService _someService;
5    public WeatherForecastController(IOptionsMonitor<WeatherOptions> weatherOptions, ISomeService someService)
6    {
7        _someService = someService;
8        _weatherOptions = weatherOptions.CurrentValue;
9    }

But what if you also had to pass those configuration settings into a piece of middleware that executes on each request, and if the configuration values change you want this to be reflected in the execution of the middleware. This is not so easy because the constructor of a middleware class can only have singletons injected into it, the same applies to the Configure method Startup.

Fortunately, the Invoke method can have a scoped service injected into it, see here for more.

 1public class SomeMiddleware
 2{
 3    private readonly RequestDelegate _next;
 4
 5    public SomeMiddleware(RequestDelegate next)
 6    {
 7        _next = next;
 8    }
 9
10    public async Task InvokeAsync(HttpContext context, ISomeService someService)
11    {
12        someService.DoSomething("Middleware - ");
13        await _next(context);
14    }
15}

To use the middleware, add a single line to the Configure method -

1public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
2{
3    app.UseMiddleware<SomeMiddleware>();
4    //snip..

That’s it.

Full source code here.

comments powered by Disqus

Related