I have a .Net 5 Web Api project and want to configure options with some logic. That's why I would like to move the configuration out from the Startup.ConfigureServices method and put them into their own service configurator (running during startup). So I came up with this
class OptionsConfigurator : IHostedService
{
private readonly IServiceCollection _serviceCollection;
public StartupOptionsConfigurator(IServiceCollection serviceCollection)
{
_serviceCollection = serviceCollection;
}
public Task StartAsync(CancellationToken cancellationToken)
{
/*
Build the ServiceProvider from the _serviceCollection
Get the IConfiguration service from the ServiceProvider
Read the configurationSection from the IConfiguration
call _serviceCollection.Configure<MyOptions>(configurationSection);
*/
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
This won't work because I can't inject IServiceCollection to the constructor. Is there a way to configure those options without the need of an instance of IServiceCollection?
I can provide another example showing the problem:
Your Api provides a single endpoint to update a specific configuration to change it during runtime (maybe change the database connection string for some reasons).
- Create a new Web Api project
- Create an options class
.
public class MyOptions
{
public string Text { get; set; }
}
- Create a controller
.
[ApiController]
[Route("[controller]")]
public class MyController : ControllerBase
{
private readonly IOptionsMonitor<MyOptions> _myOptionsMonitor;
private readonly IServiceCollection _serviceCollection;
public MyController(IOptionsMonitor<MyOptions> myOptionsMonitor, IServiceCollection serviceCollection)
{
_myOptionsMonitor = myOptionsMonitor;
_serviceCollection = serviceCollection;
}
[HttpPatch]
public IActionResult UpdateOptions([FromBody] string text)
{
Console.WriteLine("Before: " + JsonSerializer.Serialize(_myOptionsMonitor.CurrentValue));
_serviceCollection.Configure<MyOptions>(x => { x.Text = text; });
string newConfig = JsonSerializer.Serialize(_myOptionsMonitor.CurrentValue);
Console.WriteLine("After: " + newConfig);
return Ok(newConfig);
}
}
Call the patch endpoint with a new configuration string in the request body. As expected this doesn't work neither, the injection of IServiceCollection is not possible and throws an exception.
Are there any solutions on how to configure options later on?