C#
Sam Lau  

Demystifying .NET Application Development Configuration – User secrets vs appsettings.Development.json

A common question that comes up in .NET development is how to setup local configuration for development only when you are working with other developers on the same git repo. For the purpose of demoing, let’s assume we have the below appsettings.json and we would like to change the connection string during development.

{
  "MyAppConfig": {
    "AppName": "MyApplication",
    "ConnectionString": "Server=SomeServer;Database=SomeDB;User ID=SomeId;Password=SomePassword;"
  }
}

Let’s start with the naive approach and go for there.

Edit appsettings.json directly

The most obvious approach is to update appsettings.json directly and put your connection string there, like that:

{
  "MyAppConfig": {
    "AppName": "MyApplication",
    "ConnectionString": "Server=MyServer;Database=MyDB;User ID=MyId;Password=MyPassword;"
  }
}

It works but it is risky because appsetting.json is under source control. If you do a git add . and commit your change to the remote branch, you are pushing your local dev configuration, in this case your credential, to the remote branch. Even worse, if no one catch it during pull request, your credential is now in main branch for everyone to see. What a shame!

appsettings.Development.json

This is what appsettings.Development.json is for, right? You have configuration that is only for development and it should be put in appsettings.Development.json, like this:

{
  "MyAppConfig": {
    "ConnectionString": "Server=MyServer;Database=MyDB;User ID=MyId;Password=MyPassword;"
  }
}

The ConnectionString in appsettings.Development.json will override ConnectionString in appsettings.json only in Development environment. This is better then the first approach. However, appsettings.Development.json is usually under source control, which I think it should, so you have the same issue with the first one. The only relief is that production will not use your credential.

So, what is the point of appsettings.Development.json if you should not put your personal configuration there? It is meant to hold configuration there is development specific but are shared among all development environment. An example would be if your app use a specific port during development only.

User secrets

Alright. Let’s get to the meat of the post. The correct way you should inject your personal configuration is by user secrets. User secrets’ Secret Manager tool is the way .NET handle local personal configurations during development. To use it, do the following in terminal in your project directory:

dotnet user-secrets init
dotnet user-secrets set "MyAppConfig:ConnectionString" "Server=MyServer;Database=MyDB;User ID=MyId;Password=MyPassword;"

To read all the secrets you have set, you can do:

dotnet user-secrets list

For non-web project, say console application, there is some extra steps, which you can read here.

This is it! Your personal configuration is stored locally and is not tracked by source control. Be aware that this secret is not encrypted and simply stored as plain text locally. If you need a trusted store, you may look into Azure Key Vault.

Conclusion

For development configuration, the question you need to ask is should this be shared across all developers. If so, use appsettings.Development.json. If not, use user secrets. This is just for development configuration setup. For production configuration, I have another post Azure App Configuration with Azure Key Vault and Dynamic Configuration in .NET 8 Application that talks about using Azure App Configuration to populate configuration in production. If you want to dive deeper in .NET configuration, you can also read this Microsoft documentation.