--- 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)]