DEV Community

Cover image for Options and Configuration In .NET6
Maurizio8788
Maurizio8788

Posted on • Edited on

Options and Configuration In .NET6

Hi everyone, today I wanted to talk to you about one of the fundamental aspects in .NET development: namely retrieving configuration information. With the advent of .NET 6 it has become even easier to manage our applications by retrieving configuration options based on the development environment we are in using in this first article the IConfiguration interface and in a second article the Options pattern easily defining configuration options and retrieving them in a clean and structured way. This allows us to separate configuration logic from business logic, making our code more modular, maintainable and flexible.

SUBJECT INDEX:

Information retrieval by IConfiguration

In a .NET application we have the ability to set our configurations via .json or .xml files normally visible at the root of our projects, depending on the project chosen these files can correspond to the name of:

  • appsetting.json when working with WebApi or MVC

  • App.config when we work in a WPF application instead.

Configure new appsettings

In other projects such as a console application these files are not present and you have to create and register them at startup through the Microsoft.Extensions.Configuration.json library by configuring the newly created file so that at build time it can be placed in the project bin, this through these few lines of code:



public class Program
{
  private static void Main(string[] args)
  {
        var configuration = new ConfigurationBuilder()
             .SetBasePath(AppContext.BaseDirectory)                                   
             .AddJsonFile("appsettings.json",optional:true)
             .Build();
       var conn = configuration
                  .GetConnectionString("AppDbContext");
  }
}


Enter fullscreen mode Exit fullscreen mode

and of course creating the appsettings file in the root directory and setting the 'Copy to output Directory' option to on Copy Always (right click > Properties):

Image description

at this time we have a configuration file created ad hoc for our application, we set the base path where the compiler will fetch the file through the SetBasePath method and then added the AddJsonFile method of the builder entered the name of the file, and set this file as non-optional and thus generating an error in case the file is removed, next we used the GetConnectionString method to test the correct setting and retrieval of the value present in our configuration file.

The File Hierarchy

Now let's take a small step back and imagine that we have to develop a trivial application in .NET 6 MVC, within this type of project, as we pointed out earlier, we find our appsettings.json file and another file namely appsettings.development.json. The configuration files follow a real hierarchy based on the specific environment in which we are working, it should be noted that the properties of the '.development.json' file will override the main appsettings.json file.

The methods of IConfiguration

Previously we used the GetConnectionString method to retrieve from our appsettings file the property that contains our database connection string, this method is present in the IConfiguration interface, this interface we can inject it anywhere in our application through dependency injection:



public class HomeController : Controller
{
   private readonly ILogger<HomeController> _logger;
   private readonly ApplicationDbContext _context;
   private readonly IConfiguration _configuration;

   public HomeController(
      ILogger<HomeController> logger,
      IConfiguration configuration
   )
   {
     _logger = logger;
     _configuration = configuration;
   }
}




Enter fullscreen mode Exit fullscreen mode

now in order to retrieve the property within the configuration .json file, we will use two of the most commonly used methods in this interface namely:

  • GetSection

  • GetValue

GetSection will retrieve entire sections of our configuration file, GetValue instead individual values, to be clear:



{
   “Section”: {
     “Single value”:”test”
   }
}


Enter fullscreen mode Exit fullscreen mode

now suppose I have within my appsettings file the following configuration:



{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    },
  },
  "Apis": {
     "BookApi": "https://localhost:7260/api/"
  }
  "AllowedHosts": "*"
}


Enter fullscreen mode Exit fullscreen mode

If I wanted to retrieve the entire section of the outer bees, I should use the following form:

var apiSection = _configuration.GetSection(“Apis”);

this way I could retrieve in my method the individual values from the api section to create a configuration for the http client in this way:



builder.Services.AddHttpClient<BookService>(options => {
    options.BaseAddress = new Uri(apiSection["BookApi"]);
});


Enter fullscreen mode Exit fullscreen mode

now we have configured an Http client that we could use in individual services. It is not necessary to retrieve the whole "Apis" section to access our remote url, we can also modify our code as follows:



builder.Services.AddHttpClient<BookService>(options => {
    options.BaseAddress = new Uri(_configuration.GetValue<string>("Apis:BookApi");
});


Enter fullscreen mode Exit fullscreen mode

the code above other reproduces the same result, following the pattern "section:properties" we can retrieve our endpoint and initialize our view.

This is all great but you have to realize that hand-writing the various properties can lead to misspellings, you also have to take into account that if we change the names of the properties or sections, we would be forced to change all the points in our code that uses those properties or those sections, and that's not very practical especially in case of large applications and that's where .NET Core comes to our rescue.

Binding of properties with custom class

Our IConfiguration interface has another method that can help us make the retrieval of our configurations cleaner, the Bind method this method simply binds a section of our appsettings to the properties of a class we created and passed as a parameter to the method.

NB For the binding to work properly, the properties must be public and the names perfectly identical to those entered in the appsettings file.

First we create our class, which we will call ApisConfiguration:



public class ApisConfiguration
{
    public string BookApi { get; set; }
}


Enter fullscreen mode Exit fullscreen mode

next we return to the Program.cs class of our project, and only then can we retrieve our settings through the Bind method:



ApisConfiguration apiConfig = new ApisConfiguration();
builder.Configuration.Bind("Apis", apiConfig);


Enter fullscreen mode Exit fullscreen mode

and we will get the same result as before but using the property of the class which at this point will be valued m we will have a cleaner method available:



builder.Services.AddHttpClient<IBookService, BookService>(options => {
options.BaseAddress = new Uri(apiConfig.BookApi);
});

Enter fullscreen mode Exit fullscreen mode




Final Considerations

We have come to the end of our first article covered several topics we talked about the configuration hierarchy, we saw how to configure an appsettings file completely de zero and how to retrieve information using the methods provided by the IConfiguration interface, and then we used binding to connect a class we created to a particular section of our appsettings.

Now it might seem like this method of information retrieval might be more than fine, but this method is definitely very verbose we need to inject the IConfiguration and then bind the properties with our classes, the .NET Core provides us with a pattern that allows us to centralize the retrieval of our configurations at the Startup level and then inject these configurations into the classes where we need them, this is called Pattern Options.

If you liked this article of mine put a like and give me your impression on this topic, contact me on Linkedin or write me on Twitter for a discussion.

Top comments (0)