Skip to main content

How to Pass a Connection String with an Environment Variable in .NET C#

· 5 min read
Jagdish Kumawat
Founder @ Dewiride

An ASP.NET Core app reads ConnectionStrings:Inventory from wherever it's set, with no code changes. In production, that's usually an environment variable, named with a double underscore. I set one over the top of user-secrets, to see which value wins.

What You Need​

An ASP.NET Core app that reads a connection string with GetConnectionString. The example has a connection string called Inventory, and it logs its settings when it starts.

The Name​

Configuration keys use : for levels, and a colon doesn't work in every environment variable. Microsoft's documentation: "A double underscore ( __ ) is supported by all platforms and is automatically converted into a colon ( : ) when the configuration is read by the app."

In appsettings.jsonAs a configuration keyAs an environment variable
"ConnectionStrings": { "Inventory": "…" }ConnectionStrings:InventoryConnectionStrings__Inventory

Step 1: Set It for One Run​

This reads the password from a .env file, so that it stays out of your shell history:

Terminal
ConnectionStrings__Inventory="Server=127.0.0.1;Port=3306;Database=inventory;User ID=inventory_app;Password=$(grep '^MYSQL_PASSWORD=' .env | cut -d= -f2-);SslMode=Required;Maximum Pool Size=25" dotnet run --project src/Dewiride.Inventory.Api

In bash and zsh, a variable in front of a command lasts for that command. In PowerShell, it lasts until you remove it, which is what the last line does.

Step 2: See Which Value Wins​

This project also has a connection string in user-secrets, with no Maximum Pool Size:

Terminal
dotnet user-secrets list --project src/Dewiride.Inventory.Api
Output (with the password hidden)
ConnectionStrings:Inventory = Server=127.0.0.1;Port=3306;Database=inventory;User ID=inventory_app;Password=…;SslMode=Required

The app's first log line, on its own:

API log
MySQL connection: server 127.0.0.1, database inventory, user inventory_app, SslMode Required, pool up to 100, connect timeout 15 s

And with the environment variable above:

API log
MySQL connection: server 127.0.0.1, database inventory, user inventory_app, SslMode Required, pool up to 25, connect timeout 15 s

The app logging a pool of 100 from user-secrets, and a pool of 25 once ConnectionStrings__Inventory is set.

The pool went from 100 to 25, so the environment variable won. In the default setup, sources are read in this order, and a later one overrides an earlier one:

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. User-secrets, in Development only
  4. Environment variables
  5. Command-line arguments

On a Server​

Set the variable wherever your platform keeps secrets: a Kubernetes secret, your host's application settings, or a systemd EnvironmentFile that only the service can read. You don't need appsettings.json to mention it at all.

If it's missing, fail at startup with a clear message, rather than at the first request. How to Run an ASP.NET Core App as Production on Your Machine shows that.

Keys with a dot in them are a special case: export refuses them.

Common Mistakes​

MistakeWhat happensDo this instead
A single underscoreIt's a different key, and nothing reads itUse two
Using : in the name on LinuxShells won't accept itUse __
Typing the password on the command lineIt stays in your shell's historyRead it from a file
Leaving it set in a PowerShell sessionLater commands use it tooRemove-Item Env:…
A ; in the password, unquotedOption not supportedQuote it

Troubleshooting​

SymptomLikely causeFix
The variable seems ignoredA typo, or a launch profile that sets the same nameCheck the name, and launchSettings.json
It works in a terminal, and not in the serviceServices don't read your shell's variablesSet it in the service's own settings
A container gets the wrong valueYour shell beat .envCheck env

Conclusion​

ConnectionStrings__Inventory in the environment overrides what's in appsettings.json and user-secrets, with no code change. Read the password from a file, and on a server use your platform's secret store.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.