So far, all values in the Kladde are in the code: the ports in launchSettings.json, everything else in C#. An application in production, though, needs values that change without anyone touching the code: the office’s opening hours, the address of a database, a password for sending mail. In lesson 2.3.1, you already read such a value, builder.Configuration["Kladde:DataFolder"], without knowing where it could come from. In this lesson, you get to know ASP.NET Core’s configuration: its sources, their order and the place for secrets. Then you combine related values into options, classes with types and rules, and have the app check at startup whether the values are right.

At the end, the Kladde knows its booking rules: opening hours, the length of an appointment and the lead time. If one of them is set wrongly, the app doesn’t start and says which value is wrong.

A project to try things out

For this lesson, you need a project, because environments and user secrets are tied to a project file. Create it in k2-practice/2-3:

Bash
dotnet new web -o settings

As in lesson 2.3.1, set fixed ports in settings/Properties/launchSettings.json, http://localhost:5160 in the http profile, and launchBrowser to false. Then add a section Office to appsettings.json:

JSON
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Office": {
    "Name": "Kladde office",
    "City": "Leipzig",
    "Seats": 4,
    "Opens": "08:30",
    "Closes": "17:00"
  }
}

and add a name for development only to appsettings.Development.json:

JSON
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "Office": {
    "Name": "Kladde office (development)"
  }
}

For now, Program.cs only shows what the app has read:

C#
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", (IConfiguration config) =>
    $"""
    Office:      {config["Office:Name"]}
    City:        {config["Office:City"]}
    Seats:       {config["Office:Seats"]}
    Key:         {(config["Demo:ApiKey"] is null ? "missing" : "set")}
    Environment: {app.Environment.EnvironmentName}
    """);

app.Run();

IConfiguration is a service like any other from lesson 2.3.3; the handler gets it as a parameter. You will need the line with Demo:ApiKey in a moment for the user secrets. It deliberately shows only whether a key is there, never the key itself. Start with dotnet run and ask:

Bash
curl http://localhost:5160/
Office:      Kladde office (development)
City:        Leipzig
Seats:       4
Key:         missing
Environment: Development