Reading Configuration Values in Your ASP.NET Application
Tags: aspnet, appsettings, csharp
Published: 2024-03-23 12:00:28

## Prerequisites

- Some knowledge of C# and ASP.NET

## Introduction
When building our applications, we usually have some constants that are either used to handle the application setup, or are part of our application logic. We cannot necessarily hard-code these values where needed, because a change to such a value would require changes in all the files where the value is used. This is not very efficient or neat. The better way is to store these values in a configuration file, such as the appsettings.json file in our ASP.NET application. We can then read the values in our application, and any changes required would be made in just one location, the configuration file.

## Reading Configuration Values from appsettings.json
So, how do we read configuration values from our appsettings.json? We will look at two ways we can do this.

The first is by making use of the configuration object directly. In .NET 5 and below, the configuration object is an instance of ConfigurationRoot, and is present in the Startup.cs by injecting the IConfinguration interface in the constructor.
```
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;

        decimal interestRate = configuration.GetSection("LoanSettings").GetValue<decimal>("InterestRate");
    }

    public IConfiguration Configuration { get; }
}
```
In .NET 6 and above, the configuration object is an instance of ConfigurationManager, and is a property of the the application builder. So it can be accessed like so in the program.cs.
```
var builder = WebApplication.CreateBuilder(args);
var configuration = builder.Configuration;
```

We can then use a number of methods on the configuration object to read our values. Say we had our appsettings.json structured like this:
```
{
  "EnableLoans": true,
  "LoanSettings": {
    "InterestRate": 0.07,
    "DefaultLoanTenure": 6
  }
}
```
We can access the InterestRate value by calling GetSection on the configuration object, and chaining GetValue to it:
```
decimal interestRate = configuration.GetSection("LoanSettings").GetValue<decimal>("InterestRate");
```
GetSection retrieves the section with the specified key, and GetValue retrieves the value with the specified key inside that section and converts it to the type specified.

To access our configuration values outside of the Program.cs or Startup.cs, we add the IConfiguration to the constructor of the classes in which we need the configurations.
```
 public class LoanService
 {
    private readonly IConfiguration _configuration;

    public LoanService(IConfiguration configuration)
    {
        _configuration = configuration;
    }
 }
```

We can now make use of the configuration variable in the same way.

```
decimal interestRate = configuration.GetSection("LoanSettings").GetValue<decimal>("InterestRate");
```

The problem with this method is that we're loading our application's entire configuration each time we need it, just to access some specific configurations. So, this is not very performance-friendly.

A better way would be to fetch only what we need and use it in the class. We can achieve this by creating a model for the section in our appsettings.json, with properties matching the names and types of the keys we have configured. We can then bind the configurations in the section to the model on application startup.

So, we could have a class matching the LoanSettings section of our appsettings.json like this:
```
public class LoanSettings
{
    public decimal InterestRate { get; set; }
    public decimal DefaultLoanTenure { get; set; }
}
```

We can then bind this model to our LoanSettings configuration by calling the Configure method on our service collection.
```
builder.Services.Configure<LoanSettings>(configuration.GetSection("LoanSettings"));
```

We can now use the configured instance of LoanSettings like this:
```
public class LoanService
{
    private readonly IOptions<LoanSettings> _loanSettings;

    public LoanService(IOptions<LoanSettings> loanSettings)
    {
        _loanSettings = loanSettings;
    }
}
```
IOptions is used to retrieve configured instances of LoanSettings. The Value property of the IOptions holds the LoanSettings instance.
```decimal interestRate = _loanSettings.Value.InterestRate;```

We can alternatively inject the LoanSettings directly in our class constructor without wrapping it in IOptions, by adding it as a service after calling Configure on the service collection.
```
builder.Services.Configure<LoanSettings>(configuration.GetSection("LoanSettings"));
builder.Services.AddScoped(config => config.GetRequiredService<IOptions<LoanSettings>>().Value);
```

```
public class LoanService
{
    private readonly LoanSettings _loanSettings;

    public LoanService(LoanSettings loanSettings)
    {
        _loanSettings = loanSettings;
    }
}
```
We can now access the LoanSettings object directly:
```
decimal interestRate = _loanSettings.InterestRate;
```

## Conclusion
This is how we access and make use of configuration values in our application safely and efficiently.