meds
meds

Reputation: 22916

Automatically set appsettings.json for dev and release environments in asp.net core?

I've defined some values in my appsettings.json for things like database connection strings, webapi locations and the like which are different for development, staging and live environments.

Is there a way to have multiple appsettings.json files (like appsettings.live.json, etc, etc) and have the asp.net app just 'know' which one to use based on the build configuration it's running?

Upvotes: 249

Views: 425898

Answers (14)

Hossein Sabziani
Hossein Sabziani

Reputation: 3485

By adding the environment name in between the "appsettings" and ".json" part of the filename, it will override any settings that are in the main appsettings.json file.

For example, in the likehood that you have a different SQL Server connection string for a production environment, you can add that connection string to appsettings.Production.json, and it will use the value from that file.

enter image description here

To choose the profile or environment, open launchSettings.json and set the environment in ASPNETCORE_ENVIRONMENT:

   "IIS Express": {
     "commandName": "IISExpress",
     "launchBrowser": true,
     "environmentVariables": {
       "ASPNETCORE_ENVIRONMENT": "Development"
     }
   }

and setup:

var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var builder = new ConfigurationBuilder()
    .AddJsonFile($"appsettings.json", true, true)
    .AddJsonFile($"appsettings.{environment}.json", true, true)
    .AddEnvironmentVariables();

Upvotes: 9

Raihan Mahmud RAM
Raihan Mahmud RAM

Reputation: 131

Keep appsettings.json similar to appsettings.Development.json It works automatically

Example appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DefaultConnection": "Server=myserver;Database=mydb;User=myuser;Password=mypassword;"
  }
}

appsettings.Development.json

{
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Warning",
          "Microsoft.Hosting.Lifetime": "Information"
        }
      },
      "AllowedHosts": "*",
      "ConnectionStrings": {
        "DefaultConnection": "Server=myserver;Database=mydb;User=myuser;Password=mypassword;"
      }
    }

Upvotes: 2

For .NET 6.0+

Example launchSettings.json is as following

...
"profiles": {
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": false,
      "launchUrl": "swagger",
      "applicationUrl": "http://localhost:5081",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
...

We can obtain ASPNETCORE_ENVIRONMENT section as following

Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

How I use as following, in which I am using PostgreSql.

public RepositoryContext CreateDbContext(string[] args)
{
    var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

    var configuration = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile($"appsettings.{environmentName}.json")
        .Build();

    var builder = new DbContextOptionsBuilder<RepositoryContext>()
        .UseNpgsql(configuration.GetConnectionString("sqlConnection"));

    return new RepositoryContext(builder.Options);
}

Upvotes: 3

TheZero0ne
TheZero0ne

Reputation: 3

I had the same issue that I wanted to change the appsettings.*.json file based on my chosen configuration in VS and I just discovered that you can just put "$(Configuration)" as value for "ASPNETCORE_ENVIRONMENT" in your launchSettings.json.

This lets the default HostBuilder automatically pick the right appsettings.*.json-file.

I assume you still should do some other things so that your dev.appsettings won't be copied to production-server like described here for example Environment Based appsettings.json Configuration for publishing in .NET 5. But it does the trick to test different environment during development and inside VS w/o deploying to another server or to manually set the ASPNETCORE_ENVIRONMENT-variable.

BTW: I tested with VS. I am not sure whether this also works with VS-Code.

Upvotes: 0

Nick Cordova
Nick Cordova

Reputation: 754

This is version that works for me when using a console app without a web page:

var builder = new ConfigurationBuilder()
             .SetBasePath(Directory.GetCurrentDirectory())
             .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
             .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true);

            IConfigurationRoot configuration = builder.Build();
            AppSettings appSettings = new AppSettings();
            configuration.GetSection("AppSettings").Bind(appSettings);

Upvotes: 24

Oks Xen
Oks Xen

Reputation: 51

.vscode/launch.json file is only used by Visual Studio as well as /Properties/launchSettings.json file. Don't use these files in production.

The launchSettings.json file:

  1. Is only used on the local development machine.
  2. Is not deployed.
  3. contains profile settings.

    • Environment values set in launchSettings.json override values set in the system environment

To use a file 'appSettings.QA.json' for example. You can use 'ASPNETCORE_ENVIRONMENT'. Follow the steps below.

  1. Add a new Environment Variable on the host machine and call it 'ASPNETCORE_ENVIRONMENT'. Set its value to 'QA'.
  2. Create a file 'appSettings.QA.json' in your project. Add your configuration here.
  3. Deploy to the machine in step 1. Confirm 'appSettings.QA.json' is deployed.
  4. Load your website. Expect appSettings.QA.json to be used in here.

Upvotes: 5

KyleMit
KyleMit

Reputation: 29829

Update for .NET Core 3.0+

  1. You can use CreateDefaultBuilder which will automatically build and pass a configuration object to your startup class:

    WebHost.CreateDefaultBuilder(args).UseStartup<Startup>();
    
    public class Startup
    {
        public Startup(IConfiguration configuration) // automatically injected
        {
            Configuration = configuration;
        }
        public IConfiguration Configuration { get; }
        /* ... */
    }
    
  2. CreateDefaultBuilder automatically includes the appropriate appsettings.Environment.json file so add a separate appsettings file for each environment:

    appsettings.env.json

  3. Then set the ASPNETCORE_ENVIRONMENT environment variable when running / debugging

How to set Environment Variables

Depending on your IDE, there are a couple places dotnet projects traditionally look for environment variables:

  • For Visual Studio go to Project > Properties > Debug > Environment Variables:

    Visual Studio - Environment Variables

  • For Visual Studio Code, edit .vscode/launch.json > env:

    Visual Studio Code > Launch Environment

  • Using Launch Settings, edit Properties/launchSettings.json > environmentVariables:

    Launch Settings

    Which can also be selected from the Toolbar in Visual Studio

    Launch Settings Dropdown

  • Using dotnet CLI, use the appropriate syntax for setting environment variables per your OS

    Note: When an app is launched with dotnet run, launchSettings.json is read if available, and environmentVariables settings in launchSettings.json override environment variables.

How does Host.CreateDefaultBuilder work?

.NET Core 3.0 added Host.CreateDefaultBuilder under platform extensions which will provide a default initialization of IConfiguration which provides default configuration for the app in the following order:

  1. appsettings.json using the JSON configuration provider.
  2. appsettings.Environment.json using the JSON configuration provider. For example:
    • appsettings.Production.json or
    • appsettings.Development.json
  3. App secrets when the app runs in the Development environment.
  4. Environment variables using the Environment Variables configuration provider.
  5. Command-line arguments using the Command-line configuration provider.

Further Reading - MS Docs

Upvotes: 245

Jonatan Dragon
Jonatan Dragon

Reputation: 5017

In ASP.NET Core you should rather use Environment Variables instead of build configuration for proper appsettings.json

  1. Right click on you project > Properties > Debug > Environment Variables

    environment variables

  2. ASP.NET Core will use the appropriate appsettings.json file:

    example of appsettings files in solution explorer

  3. Now you can use that Environment Variable like this:

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

Note: If you use @Dmitry's answer, you can run into problems eg. when overriding appsettings.json values on Azure.

Upvotes: 64

Bharat
Bharat

Reputation: 6095

I have added screenshots of a working environment, because it cost me several hours of R&D.

  1. First, add a key to your launch.json file.

    See the below screenshot, I have added Development as my environment.

    Declaration of the environment variable in launch.json

  2. Then, in your project, create a new appsettings.{environment}.json file that includes the name of the environment.

    In the following screenshot, look for two different files with the names:

    • appsettings.Development.Json
    • appSetting.json


    Project view of appsettings JSON files

  3. And finally, configure it to your StartUp class like this:

    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
    
        Configuration = builder.Build();
    }
    
  4. And at last, you can run it from the command line like this:

    dotnet run --environment "Development"
    

    where "Development" is the name of my environment.

Upvotes: 159

user3924036
user3924036

Reputation: 283

  1. Create multiple appSettings.$(Configuration).json files like:

    • appSettings.staging.json
    • appSettings.production.json
  2. Create a pre-build event on the project which copies the respective file to appSettings.json:

    copy appSettings.$(Configuration).json appSettings.json
    
  3. Use only appSettings.json in your Config Builder:

    var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .AddEnvironmentVariables();
    
    Configuration = builder.Build();
    

Upvotes: 24

Fleaca Dan
Fleaca Dan

Reputation: 91

You can add the configuration name as the ASPNETCORE_ENVIRONMENT in the launchSettings.json as below

  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:58446/",
      "sslPort": 0
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "environmentVariables": {
        ASPNETCORE_ENVIRONMENT": "$(Configuration)"
      }
    }
  }

Upvotes: 9

Dmitry
Dmitry

Reputation: 16795

You may use conditional compilation:

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
    .SetBasePath(env.ContentRootPath)
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
#if SOME_BUILD_FLAG_A
    .AddJsonFile($"appsettings.flag_a.json", optional: true)
#else
    .AddJsonFile($"appsettings.no_flag_a.json", optional: true)
#endif
    .AddEnvironmentVariables();
    this.configuration = builder.Build();
}

Upvotes: 36

umutesen
umutesen

Reputation: 2640

Just an update for .NET core 2.0 users, you can specify application configuration after the call to CreateDefaultBuilder:

public class Program
{
   public static void Main(string[] args)
   {
      BuildWebHost(args).Run();
   }

   public static IWebHost BuildWebHost(string[] args) =>
      WebHost.CreateDefaultBuilder(args)
             .ConfigureAppConfiguration(ConfigConfiguration)
             .UseStartup<Startup>()
             .Build();

   static void ConfigConfiguration(WebHostBuilderContext ctx, IConfigurationBuilder config)
   {
            config.SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("config.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"config.{ctx.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true);

   }
 }

Upvotes: 33

Onkel Toob
Onkel Toob

Reputation: 2212

You can make use of environment variables and the ConfigurationBuilder class in your Startup constructor like this:

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
    .SetBasePath(env.ContentRootPath)
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
    .AddEnvironmentVariables();
    this.configuration = builder.Build();
}

Then you create an appsettings.xxx.json file for every environment you need, with "xxx" being the environment name. Note that you can put all global configuration values in your "normal" appsettings.json file and only put the environment specific stuff into these new files.

Now you only need an environment variable called ASPNETCORE_ENVIRONMENT with some specific environment value ("live", "staging", "production", whatever). You can specify this variable in your project settings for your development environment, and of course you need to set it in your staging and production environments also. The way you do it there depends on what kind of environment this is.

UPDATE: I just realized you want to choose the appsettings.xxx.json based on your current build configuration. This cannot be achieved with my proposed solution and I don't know if there is a way to do this. The "environment variable" way, however, works and might as well be a good alternative to your approach.

Upvotes: 45

Related Questions