In this blog entry, we look at adding configuration to Web API and other project types like console apps or tests.
Following on from my last post on Dependency Injection, I wanted to compliment it with an up-to-date guide on adding configuration. We’ll start with a Web API (since it's the simplest), and then look at adding config to other project types like console apps or tests.
Let’s Start with the API
If you create a new Web API project in Visual Studio, you’ll be presented with a couple of default files, but the ones relevant to us are:
-
appsettings.json: This is our configuration file. We’ll add some new config here in a sec.
-
Program.cs: This is the bootstrapping file that sets everything up. We’ll modify this shortly to read the configuration and expose it to our controller.
-
WeatherForecastController.cs: This is a default sample controller that Visual Studio created. We’ll modify this to read the configuration.
Step 1: Add config
Add a custom ApiSettings
section to your config. Your appsettings.json file should look something like this:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ApiSettings": {
"ApiName": "My Awesome API"
}
}
Step 2: Add a Strongly Typed config Class
Our custom section was called ApiSettings
with a single string ApiName
field, so let’s define a class with the same schema.
public class ApiSettings
{
public string ApiName { get; set; }
}
Step 3: Register config in Program.cs
Note: If you’re using a .NET version below .NET 6, then this will take place in the ConfigureServices
method of Startup.cs instead.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
Above is the auto-generated Program.cs contents of your .NET6 Web API. Before calling Build
on the builder
, add the following:
builder.Services.Configure<ApiSettings>
(builder.Configuration.GetSection("ApiSettings"));
This registers our ApiSettings
configuration section, associated with the strongly typed class we created earlier, with the .NET Dependency Injection container.
Step 4: Profit?
Now we’ve done all the heavy lifting, we can use the relevant config by injecting it into a controller or service. For demo purposes, let’s inject it into the auto-generated WeatherForecastController
.
public WeatherForecastController(ILogger<WeatherForecastController> logger,
IOptions<ApiSettings> options)
{
_logger = logger;
_apiSettings = options.Value;
}
Put a breakpoint in the constructor and observe that options
has been populated with the value(s) from our JSON config, thanks to Dependency Injection and the minimal configuration setup we did in the previous step. Just don’t forget to define the config parameters IOptions<T>
instead of just T
, which is a common mistake newcomers will make. Remember that configuration in .NET Core (and nowadays just .NET) is based on IOptions
.
Hey, What About for Non-API Projects?
You didn’t think we were done, did you? Well, I guess if you just wanted samples for a Web API project, you can leave now. But for everyone else - if you read my last post on Dependency Injection, you may remember that what makes adding DI for non-web projects non straightforward is just how much scaffolding happens automatically with the web projects. The same is true for configuration. We can achieve the same results in non-web projects, we just need to do a bit more of the heavy lifting ourselves.
Step 1: Add Packages
Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.Json
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.DependencyInjection.Abstractions
Microsoft.Extensions.Options
I’ll let you decide what versions to use - but these are the core packages that will get us started.
Step 2: Add Config File
I recommend adding the appsetting.json from our Web API project as a link to our console or test file, just to save having to reconfigure everything. Oh, and you’ll also want to add a reference to whatever project your ApiSettings
class is defined in - probably the Web API project, if you’ve just been following this guide.
Step 3: Profit?
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using SampleNet6Api;
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var services = new ServiceCollection()
.AddOptions()
.Configure<ApiSettings>(config.GetSection("ApiSettings"))
.BuildServiceProvider();
var apiSettings = services.GetService<IOptions<ApiSettings>>();
Console.WriteLine(apiSettings.Value.ApiName);
Console.ReadLine();
Above are the contents of my Program.cs in a console project, but it’ll be quite similar for test projects as well.
First, we create a ConfigurationBuilder
and populate it with the config from our JSON file. Then, we create a ServiceCollection
(the .NET DI container), add IOptions
to it and register our ApiSettings
class from the config. These two steps (minus the Configure
bit) happen automatically under the hood with Web projects.
Lastly, we grab the IOptions<ApiSettings>
service from the DI container and write the config value to the console. This is more-or-less that happened in the constructor of WeatherForecastController
in our Web API project.
And that’s about it. Happy coding (or should I say configuring), and catch ya later!