Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To use the options pattern in ASP.NET Core, define a class for a related group of settings, bind a configuration section to it, register that binding with dependency injection, and inject the options interface that fits your service lifetime and need for configuration updates. Microsoft describes options as its preferred way to read related configuration values. This guide uses the current ASP.NET Core .NET 10 guidance, last updated March 18, 2026.

1. Define a class for related settings

Create a class whose properties represent the values in one configuration section. Group settings by purpose so a service can depend on the settings it needs instead of reading individual configuration keys throughout the application.

public sealed class EmailOptions
{
    public const string SectionName = "Email";

    public string Host { get; set; } = "";
    public int Port { get; set; }
    public string FromAddress { get; set; } = "";
}

For example, the corresponding configuration can be expressed in appsettings.json like this:

{
  "Email": {
    "Host": "mail.example.com",
    "Port": 587,
    "FromAddress": "noreply@example.com"
  }
}

The class and section name are a convention you control; what matters is that the section you bind matches the configuration source and the shape of the options class.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. Bind the configuration and register it with dependency injection

In the minimal hosting model, bind the section in Program.cs using AddOptions and Bind:

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddOptions<EmailOptions>()
    .Bind(builder.Configuration.GetSection(EmailOptions.SectionName));

Microsoft also documents the shorter registration form using Configure<TOptions>:

builder.Services.Configure<EmailOptions>(
    builder.Configuration.GetSection(EmailOptions.SectionName));

Both forms connect the matching configuration section to the options type. The options pattern and ASP.NET Core registration details are documented in Microsoft’s ASP.NET Core .NET 10 options-pattern guidance.

3. Inject and read the options

Inject an options interface into the constructor of the service that needs these settings. The simplest form is IOptions<TOptions>, whose default instance is accessed through Value:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
using Microsoft.Extensions.Options;

public sealed class EmailSender
{
    private readonly EmailOptions _options;

    public EmailSender(IOptions<EmailOptions> options)
    {
        _options = options.Value;
    }

    public void Send()
    {
        var host = _options.Host;
        var port = _options.Port;
        // Use the settings to send email.
    }
}

Choose the interface based on the consumer’s lifetime and whether it needs named configurations or to observe updates:

Interface Lifetime Use it when Important behavior
IOptions<TOptions> Singleton Settings are stable and can be consumed from any service lifetime. It does not support named options or reading configuration changes after application startup.
IOptionsSnapshot<TOptions> Scoped A scoped or transient consumer needs a request-scoped view of settings. It cannot be injected into a singleton. Options are computed on access and cached for the scope; named options are supported.
IOptionsMonitor<TOptions> Singleton A singleton consumer needs named options, current values, or change notifications. Reload depends on whether the configuration source and provider support updates.

These distinctions follow Microsoft’s documentation for ASP.NET Core options and the general .NET options pattern.

4. Choose how configuration changes should be handled

Use IOptions<TOptions> for stable settings

Use IOptions<TOptions> when consumers only need the default options instance and should not read updates after startup. It can be injected into any service lifetime.

Use IOptionsSnapshot<TOptions> for scoped consumers

A snapshot is scoped and provides a view cached for that scope. It suits request-oriented or other scoped use, but a singleton cannot depend on it because that would cross the service lifetime boundary.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use IOptionsMonitor<TOptions> for singleton consumers and notifications

A monitor is singleton and supports named instances and change notifications. It is appropriate when a singleton needs the current options or must react to changes. A monitor alone does not make every configuration source reloadable: the source and provider must support updates for reload behavior to occur.

5. Configure named options when one class has multiple instances

All options instances have a name; the default instance uses the empty string. When the same settings type needs distinct configurations, register named options, for example:

builder.Services
    .AddOptions<EmailOptions>("Primary")
    .Bind(builder.Configuration.GetSection("Email:Primary"));

builder.Services
    .AddOptions<EmailOptions>("Backup")
    .Bind(builder.Configuration.GetSection("Email:Backup"));

Retrieve a named instance with Get(name) from IOptionsSnapshot<TOptions> or IOptionsMonitor<TOptions>:

public sealed class MailRouter
{
    private readonly EmailOptions _primary;

    public MailRouter(IOptionsMonitor<EmailOptions> options)
    {
        _primary = options.Get("Primary");
    }
}

For more advanced named configuration, .NET provides IConfigureNamedOptions<TOptions>. ConfigureAll and PostConfigureAll apply configuration or post-configuration across names. The options factory runs configuration actions before post-configuration actions, which is useful when defaults or derived values must be applied after binding.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

6. Validate settings and choose when errors should surface

Configuration values can be missing or invalid, so add validation rules rather than letting bad values fail later in application logic. Options validation runs when an options instance is first created; for example, when code first accesses snapshot Value or calls monitor Get(name). Validation runs again when configuration reloads.

Data annotations are useful for straightforward constraints. For more involved rules, use a predicate, IValidateOptions<TOptions>, or IValidatableObject. With the AddOptions registration, annotations and startup validation can be added like this:

using System.ComponentModel.DataAnnotations;

public sealed class EmailOptions
{
    public const string SectionName = "Email";

    [Required]
    public string Host { get; set; } = "";

    [Range(1, 65535)]
    public int Port { get; set; }

    [Required, EmailAddress]
    public string FromAddress { get; set; } = "";
}

builder.Services
    .AddOptions<EmailOptions>()
    .Bind(builder.Configuration.GetSection(EmailOptions.SectionName))
    .ValidateDataAnnotations()
    .ValidateOnStart();

Use ValidateOnStart() when invalid settings should prevent the host from starting, rather than waiting until the options instance is first accessed. For validation APIs and behavior, see Microsoft’s ASP.NET Core options guidance and .NET options documentation.

Common mistakes to avoid

  • Binding the wrong section: verify that the section name used in GetSection matches the configuration key.
  • Injecting a scoped snapshot into a singleton: use IOptionsMonitor<TOptions> or stable IOptions<TOptions> instead, depending on whether updates are needed.
  • Assuming all configuration reloads: monitor change behavior depends on provider support.
  • Leaving invalid values unchecked: add rules for required values and ranges, and select startup validation when the application should fail fast.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.