Tame Configuration in ASP.NET Core with IValidateOptions
Silent misconfiguration is sneaky and expensive. Learn how to validate strongly typed settings in .NET using IValidateOptions, add cross property rules, inject services, support named options, and fail fast at startup with ValidateOnStart.
If you have ever shipped a service that waited until 2 AM to reveal a missing config value, you know the special kind of adrenaline that only a pager can deliver.
This post shows how to stop silent misconfiguration by validating options up front using IValidateOptions. We will bind strongly typed settings, add cross property rules, inject services into validators, support named options for multiple clients, and fail fast at startup with ValidateOnStart.
The silent failure problem
Binding settings to a class is great, but binding does not imply valid. Missing or out of range values will happily slide through.
Here is a tiny options class we will use in examples.
public sealed class SmtpOptions
{
public string? Host { get; set; }
public int Port { get; set; } = 25;
public bool UseSsl { get; set; }
public string? Sender { get; set; }
}
And a minimal Program.cs that binds configuration. Nothing here prevents a null Host from sneaking into production.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOptions<SmtpOptions>()
.Bind(builder.Configuration.GetSection("Smtp"));
var app = builder.Build();
app.MapGet("/", () => "It boots, but is it valid?");
app.Run();