I have a C# console app that is pushed to Azure DevOps and then deployed to a specific server. The app uses an appsettings.json file like this:
IConfiguration _configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
In order for the file to be read correctly, I set its "Build Action" to "Content" and "Copy to Output Directory" to "Copy if newer" (is this correct?).
Currently, when I deploy to the server, the new appsettings.json overwrites the previous one. I want to prevent this.
If I add appsettings.json to .gitignore, the DevOps build fails because the file is missing.
What is the proper way to handle this scenario? I think that the correct way it to use appsettings.development.json, but I can't figure out how to setup the environment.
The quick fix is to not copy that file in the first place, but a better option would be to use the Generic .NET Host and use the default Configuration setup.
using Microsoft.Extensions.Hosting;
using IHost host = Host.CreateApplicationBuilder(args).Build();
var config=host.Services.GetService<IConfiguration>();
...
There's nothing special about appsettings.json, it's just another JSON file with settings. Any sources configured after it would overwrite its settings by key. This allows loading one set of settings and overwriting with environment/production-specific settings.
The default configuration was built to handle the very problem described in the question. The config source order is :
appsettings.json. Essentially, the default settingsappsettings.{Environment}.json, where the environment can be Development, Staging and the default, Production. The runtime checks the contents of the DOTNET_ENVIRONMENT or ASPNETCORE_ENVIRONMENT environment variable to determine that to use.This allows you do specify the defaults in appsettings.json and override them in different environments using extra files. In container environments, the orchestrator can provide overrides as environment variables. Finally, you can use command-line arguments to override everything else
You can replicate this behavior without the host by adding the relevant calls, eg :
// May want to validate this
var envName=GetEnvironmentVariable("DOTNET_ENVIRONMENT");
IConfiguration _configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: reloadOnChange)
.AddJsonFile($"appsettings.{envName}.json", optional: true, reloadOnChange: reloadOnChange)
.AddEnvironmentVariables()
.Build();
At some point I had to develop on a Mac and deploy on Windows, so I added an OS-specific appsettings....json this way :
var osName=Environment.OSVersion.Platfor.ToString();
...
.AddJsonFile($"appsettings.{osName}.json", optional: true, reloadOnChange: reloadOnChange)
.AddJsonFile($"appsettings.{osName}.{envName}.json", optional: true, reloadOnChange: reloadOnChange)
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With