ASP.NET Core Best Practices

Chapter 2 · Practice 2 of 4

Bind settings into options classes and validate them on start

From Dependency injection and configuration

Why it matters

Reading IConfiguration["Payments:ApiKey"] in services spreads magic strings everywhere and fails only when that line runs. The options pattern binds a configuration section to a class and injects it as IOptions<T>.

Add validation and run it at startup:

  • ValidateDataAnnotations() applies [Required], [Range] and similar attributes.
  • Validate(...) adds rules that span properties.
  • ValidateOnStart() (or AddOptionsWithValidateOnStart) makes a bad value stop the app at boot, not on the first request.

Pick the interface by need: IOptions<T> is a singleton read once; IOptionsSnapshot<T> is scoped and re-reads per request; IOptionsMonitor<T> is a singleton with change notifications.

Example

C#
public sealed class PaymentOptions
{
    [Required, Url] public required string BaseUrl { get; init; }
    [Required] public required string ApiKey { get; init; }
    [Range(1, 60)] public int TimeoutSeconds { get; init; } = 10;
}

builder.Services.AddOptionsWithValidateOnStart<PaymentOptions>()
    .BindConfiguration("Payments")
    .ValidateDataAnnotations();