What is the proper way to read configuration and settings?

.Net applications have a standard process for handling application configuration and settings. In my code reviews, I've observed that developers often approach configuration in a variety of unconventional or "creative" ways, which is largely incorrect. It's crucial to ensure your code can consistently load the configuration from specific locations, such as Environment Variables, Command-Line Arguments, and the application settings file, known as appsettings.json.

To achieve this, adhere to the following initialization process:

private static IConfigurationRoot InitializeConfiguration(string[] args)
{
    var builder = new ConfigurationBuilder()
         .SetBasePath(Directory.GetCurrentDirectory())
         .AddJsonFile("appsettings.json", optional: false, 
          reloadOnChange: true)
         .AddCommandLine(args)
         .AddEnvironmentVariables();

    return builder.Build();
}

This code generates the instance of a builder that allows you to manage configuration values independently of their origins. Why is this significant? Generally, we aren't certain about the packaging conditions of your library (code), or how it will be executed. For instance, your code could be operative within ASP.NET, functioning as a console application, running in a Docker container, and so on. All of these application types can utilize a variety of methods for providing the configuration, which can offer unique advantages and disadvantages depending on where the code is executed. For example, if your code is running as a console application, it's beneficial to have the settings within the appsettings.json file. However, if the same code is deployed within a Docker container, supplying the configuration as environment variables could be more effective. Therefore, it's ideal to design your code to handle all possibilities, allowing the DevOps team to make the final decision on how to provide the configuration.

Following code samples demonstrate how to read imple and complex configuration values (settings).

    //
    // Following are comming from command line.
    var color = configuration["color"];
    Console.WriteLine("{0}", color);

    var fontSize = configuration["fontSize"];
    var state = configuration["state"];

    //
    // From root of appsettings.json
    var setting1 = configuration["Setting1"];
    var setting2 = configuration["Setting2"];
    var setting3 = configuration["Setting3"];
    var sleepyState = configuration["SleepyState"];
    var aaa = configuration["AAAA"];
    var speed = configuration["Speed"];

    float i = float.Parse(setting3, CultureInfo.InvariantCulture);
    //
    // Demonstrates how to read settings from sub section.
    var section = configuration.GetSection("MySubSettings");
    var subSetting1 = section["Setting1"];
    var subSetting2 = section["Setting2"];
    var subSetting3 = section["Setting3"];

Following code shows how to read environment variables from the configuration. Please not the code has not any direct dependency to Environment class.


    var machineName = configuration["COMPUTERNAME"];
    var processor = configuration["PROCESSOR_IDENTIFIER"];
    

The variable COMPUTERNAME might also be specified inside appsettings.json file or provided as a command line argument.

More complex configuration is read as shown in following example:


   MySettings mySettings = new MySettings();
   configuration.GetSection("MySetting").Bind(mySettings);