Environment Variables in ASP.NET Core Apps

2015-06-02

IMPORTANT: This post is outdated. A new version is available here, targeting the same issue for the released version 1.x of .NET Core and ASP.NET Core.

Introduction

This post is about the pre-release version of ASP.NET Core. Read the updated version if you are working with ASP.NET Core 1.0 or later!

When writing web or console applications, you often need to access variables like the directory your app runs in, the version of the hosting environment or environment variables like the TEMP folder location or PATH and USERPROFILE variables. We also might want to store security related information, like database passwords or security tokens in a way that it doesn't end up in a configuration file which gets checked into source control.

In .Net 4.x we used static variables like AppDomain or ConfigurationManager.AppSettings which could cause all kinds of issues depending on the type and environment your app is running on. With .Net portable libraries this was also not very friendly.

Writing new apps targeting Core CLR, those constructs are not available anymore but more importantly, we don't need them anymore. With DNX the ASP.NET team wrote a great host environment for all kinds of apps, but it also comes with a lot of new concepts. For example, there are different ways to access the variables of the environment our app is running in:

  • Injecting strongly typed, host related data via dependency injection
  • Using string key, string value pairs via configuration

Runtime- and Application Environment

Those interfaces give you the information, mentioned above, in RC1 of the new ASP.NET Core applications. To get those types, you have to add the Microsoft.Extensions.PlatformAbstractions package to your project dependencies.

"dependencies": {
  "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc1-final"
}

Now, to get instances of the IRuntimeEnvironment and IApplicationEnvironment, you have to do the following depending on the type of your application.

For console applications, since RC1, the DI support got removed. Console applications are now true windows console apps with a static void Main method (the constructor of the Program will never be invoked).

But you can still get the information by calling PlatformServices.Default.

IRuntimeEnvironment runtime = PlatformServices.Default.Runtime;
IApplicationEnvironment env = PlatformServices.Default.Application;

In web apps, you'll still use constructor injection:

public App(IRuntimeEnvironment runtime, IApplicationEnvironment env)
{
}

Using both interfaces you can get the following information (example code):

public static void Main(string[] args)
{
    IRuntimeEnvironment runtime = PlatformServices.Default.Runtime;
    IApplicationEnvironment env = PlatformServices.Default.Application;

    Console.WriteLine($@"
IApplicationEnvironment:
        Base Path:      {env.ApplicationBasePath}
        App Name:       {env.ApplicationName}
        App Version:    {env.ApplicationVersion}
        Runtime:        {env.RuntimeFramework}
IRuntimeEnvironment:
        OS:             {runtime.OperatingSystem}
        OS Version:     {runtime.OperatingSystemVersion}
        Architecture:   {runtime.RuntimeArchitecture}
        Path:           {runtime.RuntimePath}
        Type:           {runtime.RuntimeType}
        Version:        {runtime.RuntimeVersion}");
}

The result will look similar to the following:

IApplicationEnvironment:
        Base Path:      C:\Temp\...
        App Name:       ConsoleApp1
        App Version:    1.0.0
        Runtime:        DNXCore,Version=v5.0
IRuntimeEnvironment:
        OS:             Windows
        OS Version:     10.0
        Architecture:   x86
        Path:           C:\Users\UserName\.dnx\runtimes\dnx-coreclr-win-x86.1.0.0-rc1-update1\bin\
        Type:           CoreClr
        Version:        1.0.0-rc1-16231

Environment Variables via Configuration

ASP.NET Core also comes with a new configuration framework. We will not go into too much detail of how this replaces app/web.config. But in general it is collection of string based key value pairs stored in JSON files or other configuration file formats depending on what you prefer.

The main NuGet package Microsoft.Framework.Configuration comes with a ConfigurationBuilder class which can be used to combine different configuration sources into one collection of key value pairs.

The subsequent packages, like Microsoft.Framework.Configuration.EnvironmentVariables and Microsoft.Framework.Configuration.Json, add extension methods to the ConfigurationBuilder to access specific configuration sources.

Example

For our example, we want to retrieve all environment variables, like PATH or USERPROFILE, and print the key and value to the console output.

We first have to add Microsoft.Framework.Configuration.EnvironmentVariables as another dependency to our project. This has already a reference to the base package and we don't have to reference it explicitly.

"dependencies": {
	"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0-rc1-final"
}

In our app, we can now instantiate a new ConfigurationBuilder and call the extension method to load the environment variables. Then, we have to call Build to actually retrieve the configuration and store them in the returned IConfiguration object.

(Optionally, you can filter the variables by prefix)

var config = new ConfigurationBuilder()
    .AddEnvironmentVariables("DNX_")
    .Build();

To print all variables to the console we can simply iterate over all available key value pairs.

foreach(var envVar in config.GetChildren())
{
    Console.WriteLine($"{envVar.Key}: {envVar.Value}");
}

There is another thing called user secrets. User secrets are retrieve from the profile of the user account the app's context is instantiate for, e.g. %APPDATA%\microsoft\UserSecrets\<applicationId>\secrets.json on windows. Read more about how to configure user secrets on the ASP.NET wiki page. The concept is the same as above mentioned environment variables, you can add the configured user secrets to the key value collection by calling the AddUserSecrets extension on the ConfigurationBuilder. You have to add the Microsoft.Extensions.Configuration.UserSecrets package to your dependencies.

More Resources and Examples