Managing Config in .Net Core

Some time ago I did few articles on how to deal with configs in .NET Framework. This article is continuation dedicated to how to do it in .NET CORE

Warning!

This article is more of an exploration of the subject then providing definitive answer. My understanding of good practices in .NET Core is not developed enough to do full answer; it is possible that a more straightforward solution exists. I am just unaware of them.

Let’s start playing with config

So If you want to use configs, Core by default supports three types of files to store configs- INI, XML, JSON. As far as I can say JSON is most popular.
First, let’s create appsettings.json and put it in project root.

Appsetting.json in root folder for now ignore the version with „prod”

Bellow is JSON file i am using for this article.:

{
  "User": {
    "Login": "Zero",
    "Password": "Megaman"
  },

  "Test": "Udany"
}

In properties you will need to set „copy to the output directory” to „copy if newer”.

As usual, if you want to make a web app you get a solution out of the box.
You have to only add something like this to Startup class.

public class Startup 
{
    public IConfigurationRoot Configuration { get; set; }

    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

        Configuration = builder.Build();
    }
}

And from now on you have access to configs.

It’s not so easy for us

Problem Is this code is automatically deploying your app to localhost.
And we don’t want that for our automation. But we can reuse some part of the mechanism for our selves

We can put this in our test setup:

   _configuration = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json", true, true)
                .Build();

in this case _configuration is a Field accessible from all tests.
Ok, thanks to this part we have added config.

So how do we get values?

Simple in our case, it will be config[„nameOfTheSetting”];

example:

        [Test]
        public void SimpleValueRead()
        {
            Console.WriteLine($" Hello { _configuration["Test"] } !");
        }

This pseudo test displeys value of „Test” from json file.

Since it is JSON, we can even use deserialization
So let’s say we are keeping user data in settings and we have such class in code:

public class User
{
    public string Login { get; set; }
    public string Password { get; set; }
}

Then we can do this:

    [Test]
    public void SectionMapping()
    {
        var test = new User();           
        _configuration.GetSection("User").Bind(test);

        Console.WriteLine($"Login: {test.Login} Password: {test.Password}");
    }

So know you know how to deal with the config file.
But we still need to deal with many environments which leads us to another question:

What about transformation?

If you need a refresher on config transformation, I have explained them in the article on how to deal with it in .net framework.
The most important thing is transformation is supported in .net core. Usually environment variable ASPNETCORE_ENVIRONMENT is used to manage on what environment you work on. For example, if you setup it to „production” your entire application will be using a production setting. Again for Web app, this works out of the box.

Unfortunately, we need to do it a little different.
But we still will be using ASPNETCORE_ENVIRONMENT to keep the naming convention.

First Setup Variable:

Open project properties,
go to debug tab

Set Launch to Project

In Environment variables add ASPNETCORE_ENVIRONMENT with values you want (i suggest the same name as environments)

Next, let’s add appropriate setting files. They should be named
appsettings.{yourenv}.json don’t forget to mark them for copping

Example of my json:

{
  "User": {
    "Login": "lol"
  },

  "Test": "UDANY"
}

what is better than our previous solution you don’t need to mark filed for transformation add only stuff you need.

Now we need to update our code.

    var env = System.Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        _configuration = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", true, true)
            .AddJsonFile($"appsettings.{env}.json", true, true)
            .Build();

But how we run it?

Well if this had been a „normal” application not unit test . We could run it using profiles:

Unfortunately, I haven’t found a similar option for a Unit test so we will have to set up the environment variable.

From the perspective of ci/cd pipeline it is easy you need only to run the command in powershell:

setx ASPNETCORE_ENVIRONMENT "envname" -m

But honestly, If I had to do it before every test run manually I would be annoyed.
Here is the point I don’t have the right solution what I present below should be treated more like work around.
So we have to go back to our project configurations. Again if you need a reminder on how to setup project configuration use this article.

So to setup enviroment variable in code we can use this command:

Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "envname");

example in code:

#if PROD
            Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Prod");
#elif TEST
            Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Test");
#endif

Just make sure you that you don’t have anything for your ci/cd build configuration.

How to use config in other classes?

Ok there is one more question you probably have
How do I use configs in my other class? I don’t want to setup it each time.
No, you shouldn’t use usually in web application this context is shared by dependency injection, we can do the same.
So to sum it up. I am not happy with this solution it feels like a workaround,
Fortunately, you can keep it in one place and if a better solution comes around, it will be easy to replace.

I have put the code for this project on GitHub.

That is all!

I hope it will help you, and if you know a better solution let me know!

Dodaj komentarz