Reputation: 14176
Currently, we use the BUILD CONFIGURATION
from the Configuration Manager
to drive web.config
and app.config
configuration-transformation in our builds.
We are in the midst of upgrading to .NET Core & a lot of examples show the use of Environment Variables
to drive configuration-transformation in appsettings.json
. But I can't seem to find examples that correctly transform the appsettings.json
file using BUILD CONFIGURATION.
Q: Is it even possible to let the BUILD CONFIGURATION transform the appsettings.json
file anymore?
Q: If so...how?
I am super not interested in going into 100+ servers & setting an environment variable in IIS.
static IHostBuilder CreateHostBuilder(string[] args)
{
var builder = new HostBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment; //<-- I dont want to do this
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
})
.UseServiceProviderFactory<ServiceRegistry>(new LamarServiceProviderFactory())
.ConfigureServices((hostContext, services) =>
{
var connectionString = hostContext.Configuration.GetConnectionString(JsonSettings.ConnectionStrings.WorkflowComponentDb);
services.AddLamar(new ContainerRegistry());
services.AddDbContext<IntegrationDbContext>((provider, options) => { options.UseSqlServer(connectionString); });
services.AddOptions();
})
.UseConsoleLifetime();
return builder;
}
Upvotes: 2
Views: 1953
Reputation: 14176
Okay, as it turns out some folks were VERY close...but here is the answer:
Why is this favorable? (to me)
I don't have to change my existing Azure DevOps pipelines.
I don't need to register ENVIRONMENTAL variables on machines.
I don't need to worry about "competing builds" on build servers.
I don't have to dedicate build servers to specific ENVIRONMENTAL variables.
I don't need to create "launch setting" files.
...all of which seem bloated & over-complicated (to me)
THAT SAID:
If you can see a reason why ENVIRONMENTAL variables are better (than this)...I would be interested in your thoughts. It just seems like "too many moving parts" (to me).
static IHostBuilder CreateHostBuilder(string[] args)
{
var builder = new HostBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
var assemblyConfigurationAttribute = Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyConfigurationAttribute>();
var buildConfiguration = assemblyConfigurationAttribute?.Configuration;
switch (buildConfiguration)
{
case "Development":
case "ModelOffice":
case "Production":
case "Release":
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{buildConfiguration}.json", optional: true, reloadOnChange: true);
break;
default:
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
break;
}
})
.UseServiceProviderFactory<ServiceRegistry>(new LamarServiceProviderFactory())
.ConfigureServices((hostContext, services) =>
{
var connectionString = hostContext.Configuration.GetConnectionString(JsonSettings.ConnectionStrings.WorkflowComponentDb);
services.AddLamar(new ContainerRegistry());
services.AddDbContext<IntegrationDbContext>((provider, options) => { options.UseSqlServer(connectionString); });
})
.UseConsoleLifetime();
return builder;
}
Upvotes: 1
Reputation: 549
For local development, in the launchSettings.json file, you can create any configurations you like, and then launch them using VS by selecting one of them in the Start button dropdown list. This way the environment variables are read from this file behind the scenes when you run the application.
For production I asked how are you deploying the app, since if you have some automation scripts you can set the environment variable in those scripts, in the part where you run/release the app, something like
dotnet run --environment Production
Apparently there's also some possibility to set it in web.config file, this may be most useful for you but I have not used it myself.
Last thing I want to mention is that the runtime will read appsettings.json
file plus appsettings.<YOUR_ASPNETCORE_ENVIRONMENT_VALUE>.json
and will override any overlapping settings from appsettings.json file with those. This is done behind the scenes and you don't have to read those files manually in the app via code, like in some other answers in this post (you still need to add them manually into the project).
Upvotes: 1
Reputation: 5102
I think you need to create some appsetting.json based on your build names like:
So there are two ways to handle the settings:
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
#if Local
.AddJsonFile("appsettings.Local.json", optional: false, reloadOnChange: true)
#elif ModelOffice
.AddJsonFile("appsettings.ModelOffice.json", optional: false, reloadOnChange: true)
//add another files
#endif
;
Configuration
name and ASPNETCORE_ENVIRONMENT
First you need to create a configuration based on the build name like this:
And in the launchSetting.json
file use this:
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "$(Configuration)"
}
And finally in the program.cs
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: false, reloadOnChange: true);
Upvotes: 1
Reputation: 35135
One way would be to define a different compilation symbol for each configuration and use that to #if X
set the environment name.
Please see Set the environment in code.
Upvotes: 1