Skip to main content
CodeOath
← All posts

.NET Core / Web API71 min total · 19 parts

Building REST APIs with ASP.NET Core: Routing, Middleware, and Dependency Injection

Part 10 of 19 · ~1 min

Configuration and the Options Pattern

Bench sends a reminder email an hour before a reservation starts, and the settings for that arrive in stacked layers — appsettings.json first, then a appsettings.Production.json specific to whatever environment is actually running, then anything set directly in the environment, then whatever's passed on the command line — where each layer is free to override whatever the one underneath it said:

{
  "ReminderSettings": {
    "SendGridFromAddress": "bench@ridgeline.edu",
    "MinutesBeforeStart": 60
  }
}

Binding that section to a real class — the options pattern — beats scattering builder.Configuration["ReminderSettings:MinutesBeforeStart"] string lookups across the codebase:

public class ReminderSettings
{
    public string SendGridFromAddress { get; set; } = "";
    public int MinutesBeforeStart { get; set; }
}

builder.Services.Configure<ReminderSettings>(builder.Configuration.GetSection("ReminderSettings"));

class ReminderSender
{
    private readonly ReminderSettings _settings;
    public ReminderSender(IOptions<ReminderSettings> options) => _settings = options.Value;
}

There's a real difference in when each of these actually looks at configuration. IOptions<T> is a singleton, and it reads configuration a single time, at startup — whatever it captured then is what every consumer gets for the rest of the process's life. IOptionsSnapshot<T> is scoped instead, so it goes back and re-reads configuration fresh on every request, which only actually buys you anything once something can change that configuration without a full redeploy — a JSON file with reload-on-change turned on, say. Bench's own SendGrid API key never touches either one as a literal string typed into appsettings.json — it lives in user secrets on Dana's laptop and an environment variable in production, the same rule that applies to any connection string or key: source control is simply not where a secret belongs.