---
title: Options pattern in ASP.NET Core
author: rick-anderson
description: Discover how to use the options pattern to represent groups of related settings in ASP.NET Core apps.
monikerRange: '>= aspnetcore-3.1'
ms.author: riande
ms.custom: mvc
ms.date: 01/13/2022
uid: fundamentals/configuration/options
---
# Options pattern in ASP.NET Core
[!INCLUDE[](~/includes/not-latest-version.md)]
:::moniker range=">= aspnetcore-7.0"
By [Rick Anderson](https://twitter.com/RickAndMSFT).
The options pattern uses classes to provide strongly typed access to groups of related settings. When [configuration settings](xref:fundamentals/configuration/index) are isolated by scenario into separate classes, the app adheres to two important software engineering principles:
* [Encapsulation](/dotnet/standard/modern-web-apps-azure-architecture/architectural-principles#encapsulation):
* Classes that depend on configuration settings depend only on the configuration settings that they use.
* [Separation of Concerns](/dotnet/standard/modern-web-apps-azure-architecture/architectural-principles#separation-of-concerns):
* Settings for different parts of the app aren't dependent or coupled to one another.
Options also provide a mechanism to validate configuration data. For more information, see the [Options validation](#options-validation) section.
This article provides information on the options pattern in ASP.NET Core. For information on using the options pattern in console apps, see [Options pattern in .NET](/dotnet/core/extensions/options).
## Bind hierarchical configuration
[!INCLUDE[](~/includes/bind7.md)]
## Options interfaces
:
* Does ***not*** support:
* Reading of configuration data after the app has started.
* [Named options](#named)
* Is registered as a [Singleton](/dotnet/core/extensions/dependency-injection#singleton) and can be injected into any [service lifetime](/dotnet/core/extensions/dependency-injection#service-lifetimes).
:
* Is useful in scenarios where options should be recomputed on every request. For more information, see [Use IOptionsSnapshot to read updated data](#ios).
* Is registered as [Scoped](/dotnet/core/extensions/dependency-injection#scoped) and therefore can't be injected into a Singleton service.
* Supports [named options](#named)
:
* Is used to retrieve options and manage options notifications for `TOptions` instances.
* Is registered as a [Singleton](/dotnet/core/extensions/dependency-injection#singleton) and can be injected into any [service lifetime](/dotnet/core/extensions/dependency-injection#service-lifetimes).
* Supports:
* Change notifications
* [named options](#named)
* [Reloadable configuration](#ios)
* Selective options invalidation ()
[Post-configuration](#options-post-configuration) scenarios enable setting or changing options after all configuration occurs.
is responsible for creating new options instances. It has a single method. The default implementation takes all registered and and runs all the configurations first, followed by the post-configuration. It distinguishes between and and only calls the appropriate interface.
is used by to cache `TOptions` instances. The invalidates options instances in the monitor so that the value is recomputed (). Values can be manually introduced with . The method is used when all named instances should be recreated on demand.
## Use IOptionsSnapshot to read updated data
Using :
* Options are computed once per request when accessed and cached for the lifetime of the request.
* May incur a significant performance penalty because it's a [Scoped service](/dotnet/core/extensions/dependency-injection#scoped) and is recomputed per request. For more information, see [this GitHub issue](https://github.com/dotnet/runtime/issues/53793) and [Improve the performance of configuration binding](https://github.com/dotnet/runtime/issues/36130).
* Changes to the configuration are read after the app starts when using configuration providers that support reading updated configuration values.
The difference between `IOptionsMonitor` and `IOptionsSnapshot` is that:
* `IOptionsMonitor` is a [Singleton service](/dotnet/core/extensions/dependency-injection#singleton) that retrieves current option values at any time, which is especially useful in singleton dependencies.
* `IOptionsSnapshot` is a [Scoped service](/dotnet/core/extensions/dependency-injection#scoped) and provides a snapshot of the options at the time the `IOptionsSnapshot` object is constructed. Options snapshots are designed for use with transient and scoped dependencies.
The following code uses .
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsSample/Pages/TestSnap.cshtml.cs" id="snippet":::
The following code registers a configuration instance which `MyOptions` binds against:
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsSample/program.cs" id="snippet":::
In the preceding code, changes to the JSON configuration file after the app has started are read.
## IOptionsMonitor
The following code registers a configuration instance which `MyOptions` binds against.
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsSample/program.cs" id="snippet":::
The following example uses :
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsSample/Pages/TestMonitor.cshtml.cs" id="snippet":::
In the preceding code, by default, changes to the JSON configuration file after the app has started are read.
## Named options support using IConfigureNamedOptions
Named options:
* Are useful when multiple configuration sections bind to the same properties.
* Are case sensitive.
Consider the following `appsettings.json` file:
:::code language="json" source="~/fundamentals/configuration/options/samples/6.x/OptionsSample/appsettings.NO.json":::
Rather than creating two classes to bind `TopItem:Month` and `TopItem:Year`, the following class is used for each section:
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsSample/Models/TopItemSettings.cs":::
The following code configures the named options:
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsSample/program.cs" id="snippet_om":::
The following code displays the named options:
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsSample/Pages/TestNO.cshtml.cs" id="snippet":::
All options are named instances. instances are treated as targeting the `Options.DefaultName` instance, which is `string.Empty`. also implements . The default implementation of the has logic to use each appropriately. The `null` named option is used to target all of the named instances instead of a specific named instance. and use this convention.
## OptionsBuilder API
is used to configure `TOptions` instances. `OptionsBuilder` streamlines creating named options as it's only a single parameter to the initial `AddOptions(string optionsName)` call instead of appearing in all of the subsequent calls. Options validation and the `ConfigureOptions` overloads that accept service dependencies are only available via `OptionsBuilder`.
`OptionsBuilder` is used in the [Options validation](#val) section.
See [Use AddOptions to configure custom repository](xref:security/data-protection/using-data-protection#add-opt) for information adding a custom repository.
## Use DI services to configure options
Services can be accessed from dependency injection while configuring options in two ways:
* Pass a configuration delegate to on . `OptionsBuilder` provides overloads of that allow use of up to five services to configure options:
```csharp
builder.Services.AddOptions("optionalName")
.Configure(
(o, s, s2, s3, s4, s5) =>
o.Property = DoSomethingWith(s, s2, s3, s4, s5));
```
* Create a type that implements or and register the type as a service.
We recommend passing a configuration delegate to , since creating a service is more complex. Creating a type is equivalent to what the framework does when calling . Calling registers a transient generic , which has a constructor that accepts the generic service types specified.
## Options validation
Options validation enables option values to be validated.
Consider the following `appsettings.json` file:
:::code language="json" source="~/fundamentals/configuration/options/samples/3.x/OptionsValidationSample/appsettings.Dev2.json":::
The following class is used to bind to the `"MyConfig"` configuration section and applies a couple of `DataAnnotations` rules:
:::code language="csharp" source="~/fundamentals/configuration/options/samples/3.x/OptionsValidationSample/Configuration/MyConfigOptions.cs" id="snippet":::
The following code:
* Calls to get an that binds to the `MyConfigOptions` class.
* Calls to enable validation using `DataAnnotations`.
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsValidationSample/Program.cs" id="snippet":::
The `ValidateDataAnnotations` extension method is defined in the [Microsoft.Extensions.Options.DataAnnotations](https://www.nuget.org/packages/Microsoft.Extensions.Options.DataAnnotations) NuGet package. For web apps that use the `Microsoft.NET.Sdk.Web` SDK, this package is referenced implicitly from the shared framework.
The following code displays the configuration values or the validation errors:
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsValidationSample/Controllers/HomeController.cs" id="snippet":::
The following code applies a more complex validation rule using a delegate:
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsValidationSample/Program.cs" id="snippet_mc":::
### `IValidateOptions` and `IValidatableObject`
The following class implements :
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsValidationSample/Configuration/MyConfigValidation.cs" id="snippet":::
`IValidateOptions` enables moving the validation code out of `Program.cs` and into a class.
Using the preceding code, validation is enabled in `Program.cs` with the following code:
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsValidationSample/Program.cs" id="snippet_xm":::
Options validation also supports . To perform class-level validation of a class within the class itself:
* Implement the `IValidatableObject` interface and its method within the class.
* Call in `Program.cs`.
### `ValidateOnStart`
Options validation runs the first time an , , or implementation is created. To run options validation eagerly, when the app starts, call in `Program.cs`:
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsValidationSample/Snippets/Program.cs" id="snippet_ValidateOnStart" highlight="4":::
## Options post-configuration
Set post-configuration with . Post-configuration runs after all configuration occurs:
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsValidationSample/Program.cs" id="snippet_p1" highlight="10-99":::
is available to post-configure named options:
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsSample/program.cs" id="snippet_nmo" highlight="10-14":::
Use to post-configure all configuration instances:
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsValidationSample/Program.cs" id="snippet_p3" highlight="10-99":::
## Access options in `Program.cs`
To access or in `Program.cs`, call on :
:::code language="csharp" source="~/fundamentals/configuration/options/samples/6.x/OptionsSample/program.cs" id="snippet_grs":::
## Additional resources
* [View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/fundamentals/configuration/options/samples) ([how to download](xref:index#how-to-download-a-sample))
:::moniker-end
[!INCLUDE[](~/fundamentals/configuration/options/includes/options6.md)]