The benefits & implementation of the ‘Options Pattern’ in ASP.NET Core

The benefits & implementation of the ‘Options Pattern’ in ASP.NET Core

As developers we know configuration is extremely important and is used in most projects. Injecting in IConfiguration into dependencies and retrieving it by key like this: _configuration["Section:Key"] is a common approach.

Hard coding strings is nasty and so is leaking configuration into dependencies that may not require it. The Options pattern fixes this allowing configuration to be bound directly to a class. Configuration can then be isolated to where it is required, adhering to the encapsulation principle and separation of concern. This means classes only have access to the section of configuration they require. You can even go a step further and add validation logic too, but I won’t cover that in this post. You can read about this further here. https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-3.0#general-options-configuration

Here is a full example.

So firstly we add the Beer class to the service container with Configure and bind it to the beer configuration section:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.Configure<Beer>(Configuration.GetSection("Beer"));
}

Beer is injected into our BeerController as IOptions<Beer> so we call . .Value which returns type Beer.

public class BeerController : ControllerBase
{
    private readonly Beer _beer;
    public BeerController(IOptions<Beer> beer)
    {
        _beer = beer?.Value;
    }

    [HttpGet]
    public IActionResult Get()
    {
        return Ok();
    }
}

We can now see the _beer variable is populated with the correct values pulled from the appsettings.json.

And that’s it, we have injected in the configuration section we require without pointlessly injecting in the whole app configuration, and also it is typed directly to a class, meaning we can use it like this:

var peroniOrigin = _beer.Peroni;