ASP.NET Core开箱即用,具有“多环境”的概念,该概念使您的应用可以根据运行的环境使用不同的设置。例如,您可以拥有开发/测试/生产环境,每个环境都有自己的环境设置文件,以及所有环境共享的通用设置文件,还能再多吗?
1.多环境支持
appsettings.json: 全局设置appsettings.Development.json:特定于开发环境的设置appsettings.Staging.json:特定于测试环境的设置appsettings.Production.json:特定于生产环境的设置
使用默认配置,特定于环境的设置将覆盖全局设置,因此,如果已经在全局设置文件中指定了不变的设置,则不必在每个环境中都指定不变的设置。
当然,您可以使用自己喜欢的任何名称的环境。开发/测试/生产只是一个惯例。
您可以通过ASPNETCORE_ENVIRONMENT环境变量或--environment命令行开关指定要使用的环境。在Visual Studio中工作时,通常在启动配置文件中执行此操作Properties/launchSettings.json。
2、局限
此功能非常方便,但有时还不够。即使在给定的环境中,您可能也需要不同的设置来测试不同的方案。
作为一个具体的例子,我开发了一个解决方案,其中包括一个Web API和一个身份验证服务器。该API使用身份验证服务器提供的JWT承载令牌对用户进行身份验证。大多数时候,当我使用API时,不需要对身份验证服务器进行更改,并且我非常高兴使用在阿里云开发环境中部署的身份验证服务器。但是,当我确实需要对身份验证服务器进行更改时,我必须修改API设置,以便它改用本地身份验证服务器。而且我必须小心,不要提交更改,以免破坏阿里云中的开发实例。这是一个小问题,但很烦人……
一种可能的解决方案是使用其自己的设置文件创建一个新的“ DevelopmentWithLocalAuth”环境。但是设置将与开发环境中的设置相同,唯一的更改是身份验证服务器URL。我讨厌同一件事有多个副本,因为要使它们保持同步是很痛苦的。我真正想要的是一种使用开发环境设置的方法,而无需修改开发环境设置即可覆盖我的需求。
3、引入“ 子环境”
这不是一个实际的功能,只是我起的一个名字。但要点是,您可以轻松引入另一个“级别”的配置设置,仅覆盖“父”环境的某些设置。
例如,在我的场景中,我想引入一个appsettings.Development.LocalAuth.json文件,该文件继承开发环境的设置,并且仅覆盖身份验证服务器的URL:
{
"Authentication": {
"Authority": "https://localhost:6001"
}
这样做的方法是在构建主机时,将新文件添加为配置源Program.cs:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, builder) =>
{
string subenv = context.Configuration["SubEnvironment"];
if (!string.IsNullOrEmpty(subenv))
{
var env = context.HostingEnvironment;
builder.AddJsonFile($"appsettings.{env.EnvironmentName}.{subenv}.json", optional: true, reloadOnChange: true);
}
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
备注:此代码适用于ASP.NET Core 3.0 +,但是如果您使用ASP.NET Core 2.0 的WebHostBuilder代替,则同样适用HostBuilder。
魔术发生在调用ConfigureAppConfiguration时。它添加了一个新的JSON文件,其名称取决于环境和子环境。由于此配置源是在现有配置源之后添加的,因此它将覆盖以前的源提供的设置。
子环境的名称是从主机配置中检索的,主机配置本身是基于以ASPNETCORE_和命令行参数开头的环境变量。因此,要指定您想要“ LocalAuth”子环境,您需要将ASPNETCORE_SUBENVIRONMENT环境变量设置为“ LocalAuth”。
就是这样!您可以针对特定方案优化现有环境了。
4、再次升级
由于新的配置源是最后添加的,因此它将覆盖所有以前的配置源,而不仅仅是默认appsettings.json文件。
默认的主机构建器在JSON文件之后添加用户机密,环境变量和命令行参数,因此子环境设置也将覆盖这些内容。
这不是很理想的,但对于大多数情况而言可能不是主要问题。但我们需要解决它,怎么办?
解决方法是将子环境配置源插入到现有JSON源之后,但在用户密钥源之前。它使代码更加复杂,但是可行:
...
.ConfigureAppConfiguration((context, builder) =>
{
string subenv = context.Configuration["SubEnvironment"];
if (!string.IsNullOrEmpty(subenv))
{
var env = context.HostingEnvironment;
var newSource = new JsonConfigurationSource
{
Path = $"appsettings.{env.EnvironmentName}.{subenv}.json",
Optional = true,
ReloadOnChange = true
};
newSource.ResolveFileProvider();
var lastJsonConfigSource = builder.Sources
.OfType<JsonConfigurationSource>()
.LastOrDefault(s => !s.Path.Contains("secrets.json"));
if (lastJsonConfigSource != null)
{
var index = builder.Sources.IndexOf(lastJsonConfigSource);
builder.Sources.Insert(index + 1, newSource);
}
else
{
builder.Sources.Insert(0, newSource);
}
}
})
...
5、小结
关注楼主,不迷路!