ChatGPT解决这个技术问题 Extra ChatGPT

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?


K
KyleMit

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(); public class Startup { public Startup(IConfiguration configuration) // automatically injected { Configuration = configuration; } public IConfiguration Configuration { get; } /* ... */ } CreateDefaultBuilder automatically includes the appropriate appsettings.Environment.json file so add a separate appsettings file for each environment: 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:

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


Thanks, it is good but How to do that with the console process (or worker process template/scaffolding)?
This does not work with latest version, it will always take appsettings.json and ignore appsettings.development.json. Run (dev) and run (prod) is also missing.
This should be the accepted answer.
Would this work for custom environment names as well? For example, if I wanted to set ASPNETCORE_ENVIRONMENT as "Dev". Will an appsettings called appsettings.Dev.json be automatically picked up?
@Mehnaz, I believe so. I don't think you're bound by any preset available environment names. It'll just take whatever name you set in your environment variable and use that to build the naming rules for the app settings file.
K
KyleMit

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.


Tried this and it works great. VS2017 even displays the different versions as under the base file. up vote.
how do you do it in core 2.2 as ihostingenvironment is deprected
@djack109 you should use IWebHostEnvironment instead.
K
KyleMit

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.


O
Onkel Toob

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.


I looked at using environment variables, in the project properties->debug section, however there's no obvious way how this will change based on project settings. Is that another file I can add to my project to handle it?
Setting the variable within the project properties will only work for using it in your development environment (probably Visual Studio). You will need to set it elsewhere for your deployed apps depending on the specific environment (IIS, Azure). I would not recommend to set the variable in some configuration file because this file might get deployed, too, and then override the server values.
You set it up in build configurations. If there is not a build configuration file then they are doing it manually, so they would need to set it up in the (archaic) deployment profile
I have multiple environments like test, staging and production in Azure. Where do I change ASPNETCORE_ENVIRONMENT variable if I want to publish the release build of web app from VS to Azure?
We don't change the variables during deployment, instead, they are built in to the specific environment. In Azure, you can set these values directly within your app service configuration unter "Application settings". Don't forget to mark them as "Deployment slot settings" in case you're working with multiple slots.
D
Dmitry

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();
}

You should set your environment variable in your MSBuild/TFS build. Conditional compilation leads to mistakes for something easily handled in CI builds. I.e., .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
See my answer (stackoverflow.com/a/50331886/1319086) for Environment variable
This kind of approach forces the code to be recompiled specifically for each environment, making it impossible to be redistributed/installed elsewhere.
Question was about “knowing about build configuration”
This should not be marked as the accepted answer - though it is a solution it's not best practice.
u
umutesen

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);

   }
 }

How do you switch between the environments being used? Are there changes supposed to be made in any config file? I understand I'll need to add the URL I want to be using when the project runs on Azure to appsettings.json and the URL I want to execute when run locally (by F5) to appsettings.Development.json. Is that correct? My string that I want to be using is in the file launchSettings.json and I'm a bit unclear on how to alter it based on where the application is executed (or if it's supposed to be altered at all).
@DonkeyBanana The environment is nothing more than a setting specified in project properties. In VS 2017, right click on the project > properties. Under debug, you will see the current environment for key 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
Creates an 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(...
It's worth noting that here it states "AddJsonFile is automatically called twice when you initialize a new host builder with CreateDefaultBuilder". In other words, it is already loading appSettings.json and then based on your environment configuration, it is loading appsettings.{Environment}.json
@umutsen In latest visual studio there is no more run environment settings
K
KyleMit

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();


This should be an accepted answer. For complicated cases SlowCheetah may be used.
How do you create a pre-build event on the project? Where should that line starting copy... actually be put?
@Paul In Visual Studio, right-click on the Project in the Solution Explorer view, select Properties from the right-click menu, then select Build Events in the properties view.
This is perfect - allows me to build the app and deploy our QA/Test and UAT onto the one machine without having to copy the app settings and using the above methods of setting it at machine level. Exactly what was needed - and I think what the person was looking for above.
N
Nick Cordova

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);

L
LuFFy

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)"
      }
    }
  }

O
Oks Xen

.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.


Does it meant, that if you have 5 environments and 5 appsettings.EnvName.json files, all of them will be deployed and just one selected machine because artifacts of the build definition will contain all 5 files ? Or only appsettings.json (as main) + appsettings.CurrentEnvironment.json (as overrides) should be deployed and how?
T
TheZero0ne

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.