ASP.NET Core cookbook · Beginner
Bind and validate options at startup
A missing or invalid setting only shows up when the code path runs in production.
Approach
Bind configuration sections to options classes, validate with data annotations and custom rules, and call
ValidateOnStart() so the app refuses to start with bad configuration.
Solution
using System.ComponentModel.DataAnnotations;
using Microsoft.Extensions.Options;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOptions<SmtpOptions>()
.BindConfiguration(SmtpOptions.Section)
.ValidateDataAnnotations()
.Validate(o => o.Port != 25 || !o.RequireTls, "Port 25 doesn't support TLS here")
.ValidateOnStart();
builder.Services.AddSingleton<EmailSender>();
var app = builder.Build();
app.Run();
public class SmtpOptions
{
public const string Section = "Smtp";
[Required] public string Host { get; set; } = "";
[Range(1, 65535)] public int Port { get; set; } = 587;
public bool RequireTls { get; set; } = true;
[Required, EmailAddress] public string From { get; set; } = "";
}
public class EmailSender(IOptionsMonitor<SmtpOptions> options)
{
public string Describe() => $"{options.CurrentValue.Host}:{options.CurrentValue.Port}";
}
{
"Smtp": { "Host": "smtp.example.com", "Port": 587, "From": "[email protected]" }
}
Pitfalls
- Injecting
IConfigurationeverywhere and reading string keys. IOptionsSnapshot<T>in singletons (it's scoped); useIOptionsMonitor<T>.- Secrets in appsettings.json; use environment variables (
Smtp__Password), user secrets or a vault.
Variations
- Use the options validation source generator (
[OptionsValidator]) for trimming and AOT. - Named options (
Configure<T>("name", ...)) for several instances of the same settings.
Further reading: Options pattern
Reference: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options
More ASP.NET Core recipes
- Accept file uploads with size and type limits
- Add OpenTelemetry traces and metrics
- Apply EF Core migrations safely during deployment
- Cache responses with output caching and evict by tag
- Call external APIs with typed HttpClients and resilience
- Configure CORS for a browser front end
- Expose liveness and readiness health checks
- Generate OpenAPI documents with Microsoft.AspNetCore.OpenApi