This article will teach you how to read data from the appsettings.json file in ASP .NET Core.
Why do we need configuration files?
The configuration files separate an application's settings from its core source code. This is where you store:
- Database connection string
- Routes of HTTP clients you're calling
- Client credentials
- Logging configuration, etc.
Consider the following data in the appsettings.json file:
{
"Name": "Mirza",
"AgeOfBirth": 1994,
"IsAwesome": true,
"Hobbies": ["ASP .NET", "Node.js", "Call of Duty"],
"Europe": {
"Bosnia": {
"Capital": "Sarajevo",
"Founded": 1461
}
}
}
How to read these values in the controller or service class?
IConfiguration
The IConfiguration interface represents a set of key/value application configuration properties. It lives in the Microsoft.Extensions.Configuration namespace and is used to read the configuration from appsettings.json or environment files.
It can be injected into any constructor:
public class MyService(IConfiguration configuration)
{
...
}
Reading simple values
{
"Name": "Mirza"
}
To read the property from settings, use the GetValue<T>() method on the configuration object:
var name = configuration.GetValue<string>("Name"); // Mirza
The method requires the correct property name in appsettings.json. If you pass something that doesn't exist, it'll return null:
var name = configuration.GetValue<string>("ABC"); // null
That said, the configuration isn't case sensitive.
var name1 = configuration.GetValue<string>("Name"); // Mirza
var name2 = configuration.GetValue<string>("name"); // Mirza
var name3 = configuration.GetValue<string>("NAME"); // Mirza
var name4 = configuration.GetValue<string>("nAME"); // Mirza
The same applies to other simple types:
var born = configuration.GetValue<int>("AgeOfBirth"); // 1994
var isAwesome = configuration.GetValue<bool>("IsAwesome"); // true
Reading nested values
Given the settings object, how to the values of nested properties?
"Bosnia": {
"Capital": "Sarajevo",
"Founded": 1461
},
Use the parent property name, followed by the separator :, then the child property:
var capital = configuration.GetValue<string>("Bosnia:Capital"); // "Sarajevo"
var founded = configuration.GetValue<int>("Bosnia:Founded"); // 1461
This works even with deeply nested objects, e.g:
"Europe": {
"Bosnia": {
"Capital": "Sarajevo",
"Founded": 1461
}
},
var capital = configuration.GetValue<string>("Europe:Bosnia:Capital"); // Sarajevo
Alternative syntax
The shorthand syntax configuration["property"] allows you to read simple values as a string.
var name = configuration["Name"]; // "Mirza"
var bornAsString = configuration["AgeOfBirth"]; // "1994"
var isAwesomeAsString = configuration["IsAwesome"]; // "True"
That said, you need to convert a string to another primitive type:
var born = int.Parse(bornAsString); // 1994
var isAwesome = bool.Parse(isAwesomeAsString); // true
This syntax can also be used to retrieve nested values:
var capital = configuration["Europe:Bosnia:Capital"];
Reading arrays
For more complex types, we need to use the configuration.GetSection("object") method. This method takes the name of the object from appsettings, then calls Get<T>() that maps the object into the appropriate T type:
var hobbies = configuration.GetSection("Hobbies").Get<string[]>();
// ["ASP .NET", "Node.js", "Call of Duty"]
Reading objects
Likewise, use the GetSection() to extract whole objects.
Start by creating a model class:
public class Europe
{
public Country Bosnia { get; set; }
}
public class Country
{
public string Capital { get; set; }
}
Then, map it in your class:
var section = configuration.GetSection("Europe").Get<Europe>();
// Europe { Bosnia = Country { Capital = "Sarajevo" } }
Reading DB connection
It's a common practice to keep the database connection string in the appsettings.json file:
"ConnectionStrings": {
"GamesDB": "Server=<SERVER_NAME>;Database=<DATABASE_NAME>;Integrated Security=True;TrustServerCertificate=True;"
},
Although the previously mentioned approach would still work, the IConfiguration interface exposes a special method: configuration.GetConnectionString("...").
Here I'm using the builder.Configuration (which uses IConfiguration) to read the connection string in the Program.cs file, then inject it in the DB Context:
// π
var connectionString = builder.Configuration.GetConnectionString("GamesDB");
builder.Services.AddDbContext<GamesContext>(options =>
options.UseSqlServer(connectionString));
IOptions
The IOptions<T> binds specific configuration sections to strongly typed C# classes. It's used to extract specific sections (objects) and inject them into service methods.
Say you want to extract just the VapidConfig from the following file:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"VapidConfig": {
"Email": "you@example.com",
"PublicKey": "PUBLIC_KEY",
"PrivateKey": "PRIVATE_KEY"
}
}
Instead of pulling the entire thing via IConfiguration, you can focus on your object using IOptions.
public class VapidConfig
{
public string Email { get; init; } = string.Empty;
public string PublicKey { get; init; } = string.Empty;
public string PrivateKey { get; init; } = string.Empty;
}
Registering dependencies via the Options Pattern
This is where you map the VapidConfig section from appsettings.json into the previously created model. This is done using the Configure<T>() method on the builder.Services:
// Program.cs
builder.Services.Configure<VapidConfig>(builder.Configuration.GetSection("VapidConfig"));
Using the Options pattern
Just inject the model into the constructor and wrap it with IOptions<>:
public class YourService(IOptions<VapidConfig> config)
{
private readonly VapidDetails _vapidDetails = new(
config.Value.Email,
config.Value.PublicKey,
config.Value.PrivateKey
);
}
The primary difference is the config encapsulation. The user working with IOptions<T> only has access to values for the selected object, rather than the entire configuration file.
Order of precedence
ASP. NET Core projects use multiple configuration files for each environment. Out of the box, you get the appsettings.json (default and production) and appsettings.Development.json (for development).
If two files share the same properties with different values and you're running the app locally, then everything in the development file will override the default appsettings file:
// appsettings.Development.json
{
"Name": "Batman"
}
var name = configuration["Name"]; // "Batman"

Top comments (0)