# How To Use The Options Pattern In ASP.NET Core 7

> In this week's newsletter I want to show you how you can use the powerful Options pattern in ASP.NET Core 7. The options pattern uses classes to provide strongly typed settings in your application at runtime, with values typically coming from application configuration.

Published: 2022-11-19. Author: Milan Jovanović.

Canonical: https://milanjovanovic.tech/blog/how-to-use-the-options-pattern-in-asp-net-core-7

The **options pattern** uses classes to provide strongly typed settings in your application at runtime.
You bind a configuration section to an options class with `IServiceCollection.Configure`, and consume it through dependency injection with `IOptions`.
The values can come from multiple sources, most commonly application configuration.

In this week's newsletter I want to show you how you can use
the powerful **options pattern** in **ASP.NET Core 7**.

The **options pattern** uses classes to provide **strongly typed settings**
in your application at runtime.

The values for the **options** instance can come from multiple sources.
The typical use case is to provide the settings from application configuration.

You can configure the **options pattern** in a few different ways in **ASP.NET Core**.
I want to discuss some of the approaches and their potential benefits.

Let's dive in.

## Creating The Options Class

I want to set the stage first, by creating the **options** class and
explaining what settings we want to bind to it.

We want to configure [**JWT Authentication**](https://milanjovanovic.tech/blog/jwt-authentication-aspnetcore) for our application,
so we decided to create the `JwtOptions` class to hold that configuration:

```csharp
public class JwtOptions
{
    public string Issuer { get; init; }
    public string Audience { get; init; }
    public string SecretKey { get; init; }
}
```

And let's imagine that inside of our `appsettings.json` file
we have the following configuration values:

```json
"Jwt": {
    "Issuer": "Gatherly",
    "Audience": "Gatherly",
    "SecretKey": "dont-tell-anyone!"
}
```

Alright, that's looking good. Now I want to show you a few ways to bind
the values from JSON to our `JwtOptions` class.

## Setting Up Options Pattern Using IConfiguration

The most straightforward approach is to use the `IConfiguration` instance
that we can access while registering services.

We need to call the `IServiceCollection.Configure<TOptions>` method,
and specify the `JwtOptions` as the generic argument:

```csharp
builder.Services.Configure<JwtOptions>(
    builder.Configuration.GetSection("Jwt"));
```

It doesn't get simpler than this, does it?

The only downside is that we are limited to the configuration
values provided through application configuration.

This can be extended to include environment variables and user secrets also.

## Setting Up Options Pattern Using IConfigureOptions

If you want a more robust approach, I have you covered.
We're going to use the `IConfigureOptions` interface to define a class
to configure our **strongly typed options**.

There are two steps that we need to follow in this case:

- Create the `IConfigureOptions` implementation
- Call `IServiceCollection.ConfigureOptions<TOptions>` with our `IConfigureOptions`
  implementation as the generic argument

To start off, we will create the `JwtOptionsSetup` class:

```csharp
public class JwtOptionsSetup : IConfigureOptions<JwtOptions>
{
    private const string SectionName = "Jwt";
    private readonly IConfiguration _configuration;

    public JwtOptionsSetup(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public void Configure(JwtOptions options)
    {
        _configuration
            .GetSection(SectionName)
            .Bind(options);
    }
}
```

We wrote more code, to achieve the same thing. Was it worth it?

Perhaps, if you consider that we now have access to **dependency injection** in the `JwtOptionsSetup` class.
This means that we can resolve other services that we can use to get the configuration values.

We also need to tell the application to use the `JwtOptionsSetup` class:

```csharp
builder.Services.ConfigureOptions<JwtOptionsSetup>();
```

When we try to inject our `JwtOptions` somewhere, the `JwtOptionsSetup.Configure`
method will be called first the calculate the correct values.

## Injecting Options With IOptions

We've seen a few examples for how to configure the **options pattern** with the `JwtOptions` class.

But how do we actually use the **options pattern**?

Easy, you just need to inject `IOptions<JwtOptions>` from the constructor.

I'll just show the `JwtProvider` constructor here, for brevity.

```csharp
public JwtProvider(IOptions<JwtOptions> options)
{
    _options = options.Value;
}
```

The actual `JwtOptions` instance is available on the `IOptions<JwtOptions>.Value` property.

The `IOptions` instance that we injected here is configured
as a **Singleton** in dependency injection. This is very important to be aware of.

## What About IOptionsSnapshot and IOptionsMonitor?

If you want to use the latest configuration values every time
you inject an **options** class, then injecting `IOptions` won't work.

However, you can use the `IOptionsSnapshot` interface instead:

- It provides the latest configuration snapshot (cached per request)
- It is registered as a **Scoped** service
- It detects configuration changes after application start

You can also use the `IOptionsMonitor` which retrieves the current
option values at any time, and it's a **Singleton** service.

## Wrapping up

The **options pattern** gives us a way to use strongly typed configuration classes in our application.

We can configure the options class in a simple way with [`IConfiguration`](#setting-up-options-pattern-using-iconfiguration),
or we can create an [`IConfigureOptions`](#setting-up-options-pattern-using-iconfigureoptions)
implementation if we need something more powerful.

When it comes to using the **options pattern**, we have three approaches:

- [`IOptions`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.options.ioptions-1?view=dotnet-plat-ext-7.0)
- [`IOptionsSnapshot`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.options.ioptionssnapshot-1?view=dotnet-plat-ext-7.0)
- [`IOptionsMonitor`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.options.ioptionsmonitor-1?view=dotnet-plat-ext-7.0)

Deciding which of them to use in your application depends on what kind of behavior you want.
If you don't need to support refreshing configuration values
after application start, [`IOptions`](#injecting-options-with-ioptions) is a perfect solution.

---

## Frequently asked questions

### What is the options pattern in ASP.NET Core?

The options pattern uses classes to provide strongly typed settings in your application at runtime. The values can come from multiple sources, most commonly application configuration such as appsettings.json, and you consume them through dependency injection.

### How do you configure the options pattern with IConfiguration?

Call IServiceCollection.Configure with your options class as the generic argument and pass in the matching configuration section from builder.Configuration.GetSection. It is the simplest approach, limited to values coming from application configuration, which can extend to environment variables and user secrets.

### What is IConfigureOptions used for?

IConfigureOptions lets you move options setup into a dedicated class that you register with ConfigureOptions. The setup class participates in dependency injection, so it can resolve other services to compute configuration values, which is more powerful than binding a configuration section directly.

### What is the difference between IOptions, IOptionsSnapshot, and IOptionsMonitor?

IOptions is a Singleton and does not pick up configuration changes after application start. IOptionsSnapshot is a Scoped service that provides the latest configuration snapshot, cached per request. IOptionsMonitor is a Singleton that retrieves the current option values at any time.

### Does IOptions update when configuration changes?

No. IOptions is registered as a Singleton, so it keeps the values it was configured with. If you need the latest configuration values after application start, inject IOptionsSnapshot or IOptionsMonitor instead.
