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?
Update for .NET Core 3.0+
You can use CreateDefaultBuilder which will automatically build and pass a configuration object to your startup class: WebHost.CreateDefaultBuilder(args).UseStartup
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:
For Visual Studio Code, edit .vscode/launch.json > env:
Using Launch Settings, edit Properties/launchSettings.json > environmentVariables: Which can also be selected from the Toolbar in Visual Studio
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:
appsettings.json using the JSON configuration provider. appsettings.Environment.json using the JSON configuration provider. For example: appsettings.Production.json or appsettings.Development.json App secrets when the app runs in the Development environment. Environment variables using the Environment Variables configuration provider. Command-line arguments using the Command-line configuration provider.
Further Reading - MS Docs
App startup in ASP.NET Core
Configuration in ASP.NET Core
Use multiple environments in ASP.NET Core
I have added screenshots of a working environment, because it cost me several hours of R&D.
First, add a key to your launch.json file. See the below screenshot, I have added Development as my environment. 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 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(); } 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.
IWebHostEnvironment
instead.
In ASP.NET Core you should rather use Environment Variables instead of build configuration for proper appsettings.json
Right click on you project > Properties > Debug > Environment Variables ASP.NET Core will use the appropriate appsettings.json file: 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.
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.
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();
}
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);
}
}
ASPNETCORE_ENVIRONMENT
. The value is what will be replaced for ctx.HostingEnvironment.EnvironmentName}
. So if you set that value in properties to 'Production', the project will look for config.Production.json
file in the root folder. For more info, please view this link
Error CS0266 Cannot implicitly convert type 'Microsoft.AspNetCore.Hosting.IWebHost' to 'Microsoft.AspNetCore.Hosting.IWebHostBuilder'. An explicit conversion exists (are you missing a cast?)
in WebHost.CreateDefaultBuiler(...
Create multiple appSettings.$(Configuration).json files like: appSettings.staging.json appSettings.production.json Create a pre-build event on the project which copies the respective file to appSettings.json: copy appSettings.$(Configuration).json appSettings.json 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();
Properties
from the right-click menu, then select Build Events
in the properties view.
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);
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)"
}
}
}
.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:
Is only used on the local development machine. Is not deployed. 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.
Add a new Environment Variable on the host machine and call it 'ASPNETCORE_ENVIRONMENT'. Set its value to 'QA'. Create a file 'appSettings.QA.json' in your project. Add your configuration here. Deploy to the machine in step 1. Confirm 'appSettings.QA.json' is deployed. Load your website. Expect appSettings.QA.json to be used in here.
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.
Success story sharing