ASP.NET CoreC#Clean CodeDesign Patterns

Strongly-Typed Options Pattern & Architectural Validation in ASP.NET Core

Moving beyond IConfiguration strings: startup validation, options lifecycle, and decoupled microservice configuration.

BK

Bhushan Kadam

Principal Software EngineerDell Technologies

Jul 20265 min read

Engineering Preview: This article is part of the ongoing blog consolidation directly into this portfolio. Below is the full architectural synthesis, key takeaways, and sample implementation code.

Moving beyond IConfiguration strings: implementing strongly-typed options, startup validation, and decoupled configuration in enterprise microservices.

Key Architectural Principles

  • 01.Never inject raw IConfiguration into business logic or domain services.
  • 02.Use IOptions<T> for immutable singleton settings and IOptionsSnapshot<T> for per-request reloading.
  • 03.Chain .ValidateDataAnnotations().ValidateOnStart() to fail immediately at startup upon invalid configurations.
  • 04.Encapsulate third-party credentials and connection endpoints inside dedicated POCO options classes.

Relying on raw strings from IConfiguration across an enterprise application is an anti-pattern that leads to late-discovered runtime failures. The Options Pattern provides strongly-typed access to related settings groups while enforcing encapsulation.

In this guide, we walk through setting up IOptions<T>, IOptionsSnapshot<T>, and IOptionsMonitor<T>, while using DataAnnotations and ValidateOnStart() to ensure invalid configurations prevent faulty service startup.

We also look at sample implementations from enterprise repositories, including MailKit SMTP abstractions and JWT bearer security tokens.

1. The Hazards of Raw IConfiguration

Passing IConfiguration throughout your services violates Separation of Concerns and hides dependencies. Classes become tightly coupled to configuration structure and keys, making unit testing clumsy and refactoring perilous.

Strongly typed options POCOs isolate the configuration section into clean, testable C# records or classes that can be injected via standard dependency injection.

2. Lifecycle Differentiation: IOptions vs Snapshot vs Monitor

IOptions<T> is registered as a Singleton and calculates values once on startup. It offers the highest performance but cannot detect runtime configuration reloads.

IOptionsSnapshot<T> is Scoped and re-evaluates configuration per HTTP request, perfect for scenarios where appsettings or Key Vault configs reload dynamically.

IOptionsMonitor<T> is a Singleton that fires onChange events whenever configuration alters, essential for background workers and long-lived message processors.

3. Fail-Fast Startup Validation

Using .ValidateOnStart() introduced in .NET 6/7/8 ensures that if an engineer forgets to supply an environment variable or connection string in Kubernetes or Azure App Service, the container crashes during startup rather than crashing during a critical customer request.

ServiceCollectionExtensions.cscsharp
// ASP.NET Core Startup Validation with DataAnnotations & ValidateOnStart
public static IServiceCollection AddMessagingConfiguration(
    this IServiceCollection services, 
    IConfiguration configuration)
{
    services.AddOptions<ServiceBusOptions>()
        .Bind(configuration.GetSection(ServiceBusOptions.SectionName))
        .ValidateDataAnnotations()
        .Validate(options => 
            !string.IsNullOrWhiteSpace(options.ConnectionString) || !string.IsNullOrWhiteSpace(options.FullyQualifiedNamespace),
            "Either ConnectionString or FullyQualifiedNamespace must be configured.")
        .ValidateOnStart(); // Guarantees fail-fast on startup, not at first request!

    return services;
}
BK

Bhushan Kadam

Principal Software EngineerDell Technologies

I am a Principal Software Engineer with 13+ years of experience designing distributed systems, cloud microservices, and applied AI agent workflows. Over my career, I have engineered production systems at Dell Technologies, JustAnswer, Allscripts, Wipro PARI Robotics, and Ignite Solutions.

Continue Reading