Category Archives: Configuration

Configuration and Dependency Injection

In this post, I wrote about how to mock out the configuration for an application. What I did not cover in that post was whether it was a good idea to pass around IConfiguration. The answer is that, at least in my opinion, it’s a very bad idea.

In this post, I’d like to discuss why I think it’s a bad idea, and my take on a better idea.

Single Responsibility

The first reason is that you are, essentially, breaking the principle of single responsibility. Let’s imagine that we have a class that accepts an IConfiguration as a parameter. When you need an element from the configuration, you have to issue a command like this:

var myValue = new _configuration.GetValue<string>("MyValue");

So, what’s wrong with this? It’s not exactly complex code, and it’s intent is clear. However, your method is now doing two things: it’s doing what it was intended to do, and it’s reading from the configuration. If MyValue changes (say you want to call it “MyNewValue”) then you have to change your method – but your method should not care where, or how this value is retrieved! Let’s say my full class is this:

public class CalculateTemperature 
{
    private IConfiguration _configuration;
    public CalculateTemperature(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public bool IsFreezing(double temperature)
    {
        string scale = _configuration.GetValue<string>("TempScale");
        switch (scale)
        {
            case "Fahrenheit":
                return temperature == 32;

            case "Centigrade":
                return temperature == 0;

            case "Kelvin":
                return temperature == 273;

        }
    }
}

Okay, so I have a class, and a method – the class is responsible for temperature calculations, and the method for telling me if a given temperature is the freezing point of water. However, the IsFreezing method also gets a setting from the configuration file. What this means is that the method above already has a potential bug: what if the setting is not present, or it’s set to some other temperature scale, “Celcius” for example; so you now end up with a method that looks like this:

    public bool IsFreezing(double temperature)
    {
        string scale = _configuration.GetValue<string>("TempScale");
        switch (scale)
        {
            case "Fahrenheit":
                return temperature == 32;

            case "Centigrade":
            case "Celcius":
                return temperature == 0;

            case "Kelvin":
                return temperature == 273;

            case default:
                throw new Exception($"Temperature scale is unsupported");
        }
    }

Buy why should this method have to deal with what’s in the configuration file? A better implementation of this method would be something like this:

    public bool IsFreezing(double temperature, Scale scale)
    {
        switch (scale)
        {
            case Scale.Fahrenheit:
                return temperature == 32;

            case Scale.Centigrade:
                return temperature == 0;

            case Scale.Kelvin:
                return temperature == 273;
        }
    }

Now I can create a config full of ANSI art for all this method cares; and as a result, I can get rid of IConfiguration out of the class.

Testing

The second reason, as I think I implied, is that it is not straight-forward to mock out the IConfiguration class. That fact that I created a blog post on the subject means that it needs one (at least for me), which means it’s far too much hassle; which means that classes and methods that contain this are less likely to be tested.

The Real World

The example I’ve given above isn’t a very realistic example, and I’m sure that no-one reading this would create a method that read from the config for a setting that so clearly relates to the method; however, the following is a very common thing, and I’m sure that you have written something akin to this, somewhere (I know I have):

public class TemperatureRepository
{
    private IConfiguration _configuration;
    public CalculateTemperature(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public bool WasFreezingLastWeek(DateTime dateTime)
    {
        string connectionString = _configuration.GetValue<string>("ConnectionString");

        . . . 
    }
}

The exact same argument applies to this, as did for the method above, but this doesn’t feel so wrong. The reason is that you know what the Startup.cs call looks like when your class looks like this:

public class TemperatureRepository
{
    private string _connectionString;
    public CalculateTemperature(string connectionString)
    {
        _connectionString = connectionString;
    }

    public bool WasFreezingLastWeek(DateTime dateTime)
    {
        . . . 
    }
}

You either need to create the class before you inject it, or do something like this:

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<ITemperatureRepository>(srv => 
    {        
          new  TemperatureRepository(Configuration.GetValue<string>("ConnectionString"));
    });
}

In fact, I don’t think this looks too bad but, recently, I’ve been using a slightly different approach, which allows you to avoid this: that is to register a class that contains your config. If you have three or four values, then maybe have one config class for your entire application; if there’s more then have as many as make sense:

public void ConfigureServices(IServiceCollection services)
{
    var configClass = new ConfigClass()
    {
        ConnectionString = Configuration.GetValue<string>("ConnectionString");
    };

    services.AddScoped<ConfigClass>(configClass);
    services.AddScoped<ITemperatureRepository>();
}

Summary

I’m not sure this warranted such a long blog post, but it’s a Saturday afternoon and the pubs are closed!

Caveat

None of the code in this post has been tested – it’s all been written in OneNote – I didn’t think the specific code syntax was particularly relevant, given it’s more of an opinion post.

Short Walks – Using AppSettings.json in Asp Net Core

One of the things that is very different when you move to Asp.Net Core is the way that configuration files are treated. This partly comes from the drive to move things that are not configuration out of configuration files. It looks like the days of app.config and web.config are numbered and, in their place, we have AppSettings.Json. Here’s an example of what that new file might look like:

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AzureAppSettings": {
    "ApplicationInsightsKey": "1827374d-1d50-428d-92a1-c65fv2d73272"
  }
 
}
 

The old files were very flat and, using the configuration manager, you could simply read a setting; something like this:

var appSettings = ConfigurationManager.AppSettings;
string result = appSettings[key];

So, the first question is: can you still do this? The answer is, pretty much, yes:

public void ConfigureServices(IServiceCollection services)
{            
    IConfigurationBuilder builder = new ConfigurationBuilder()
          .SetBasePath(Directory.GetCurrentDirectory())
          .AddJsonFile("appsettings.json");
    Configuration = builder.Build();

    Configuration["AzureAppSettings:ApplicationInsightsKey"]

However, you now have the option of creating a class to represent your settings; something like:

AzureAppSettings azureAppSettings = new AzureAppSettings();
Configuration.GetSection("AzureAppSettings").Bind(azureAppSettings);

If you use this approach then you’ll need an extension library from NuGet:

Install-Package Microsoft.Extensions.Configuration.Binder

Is it better, or worse?

At first glance, it would appear that things have gotten worse; or at least, more complex. However, the previous method had one massive problem: it was a static class. The result being that most people have written their own wrapper around the ConfigurationManager class. We now have a class that can be injected out of the box; alternatively, you can split your configuration up into classes, and pass the classes around; the more I think about this, the better I like it: it makes more sense to have a class or method accept parameters that are necessary for its execution and, arguably, breaks the single responsibility principle if you’re faffing around trying to work out if you have all the operating parameters.

The other advantage here is that the configuration file can now be hierarchical. If you have well designed, small pieces of software then this might not seem like much of an advantage, but if you have 150 settings in your web.config, it makes all the difference.