.NET Core 控制台应用程序,如何为每个环境配置 appSettings?
.NET Core console application, how to configure appSettings per environment?
我有一个 .NET Core 1.0.0 控制台应用程序和两个环境。我需要能够根据我在 运行 时设置的环境变量使用 appSettings.dev.json
和 appSettings.test.json
。通过依赖注入和 IHostingEnvironment 以及 EnvironmentName env,这对于 ASP.NET 核心 Web 应用程序来说似乎非常简单。变量,但是我应该如何为控制台应用程序连接(除了编写我自己的使用 Microsoft.Framework.Configuration.EnvironmentVariables
的自定义代码)?
谢谢。
我们在 .netcore
控制台应用程序中就是这样做的。这里的关键是在你的项目中包含正确的 dependencies(可能不是全部,根据你的需要检查)和复制到输出 appSetting.json 作为你的 buildoptions
的一部分
{
"buildOptions": {
"emitEntryPoint": true,
"copyToOutput": {
"include": [
"appsettings*.json",
"App*.config"
]
}
},
using Microsoft.Extensions.Configuration;
namespace MyApp
{
public static void Main(string[] args)
{
var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var builder = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json", true, true)
.AddJsonFile($"appsettings.{environmentName}.json", true, true)
.AddEnvironmentVariables();
var configuration = builder.Build();
var myConnString= configuration.GetConnectionString("SQLConn");
}
}
您可以为 ASP.Net 核心环境变量 (ASPNETCORE_ENVIRONMENT) 执行此操作:-
using Microsoft.AspNetCore.Hosting;
using System;
public class Program {
private static string HostingEnvironment => Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
private static bool IsEnvironment(string environmentName) => HostingEnvironment?.ToLower() == environmentName?.ToLower() && null != environmentName;
private static bool Development => IsEnvironment(EnvironmentName.Development);
private static bool Production => IsEnvironment(EnvironmentName.Production);
private static bool Staging => IsEnvironment(EnvironmentName.Staging);
public static void Main(string[] args) { // Your code here }
}
然后你可以简单地使用 属性
public static void Main(string[] args) {
if (Development){
// Blow up the planet
}
}
您应该使用两个 IHostingEnvironment
接口。一个用于 ASP.NET 核心应用程序,另一个用于 .NET Core 控制台应用程序。您可以将此代码示例用于两者:
using System;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting.Internal;
namespace MyApplication.Common
{
public static class ConfigurationFactory
{
/// <summary>
/// Use for ASP.NET Core Web applications.
/// </summary>
/// <param name="config"></param>
/// <param name="env"></param>
/// <returns></returns>
public static IConfigurationBuilder Configure(IConfigurationBuilder config, IHostingEnvironment env)
{
return Configure(config, env.EnvironmentName);
}
/// <summary>
/// Use for .NET Core Console applications.
/// </summary>
/// <param name="config"></param>
/// <param name="env"></param>
/// <returns></returns>
private static IConfigurationBuilder Configure(IConfigurationBuilder config, Microsoft.Extensions.Hosting.IHostingEnvironment env)
{
return Configure(config, env.EnvironmentName);
}
private static IConfigurationBuilder Configure(IConfigurationBuilder config, string environmentName)
{
return config
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{environmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
}
/// <summary>
/// Use for .NET Core Console applications.
/// </summary>
/// <returns></returns>
public static IConfiguration CreateConfiguration()
{
var env = new HostingEnvironment
{
EnvironmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production",
ApplicationName = AppDomain.CurrentDomain.FriendlyName,
ContentRootPath = AppDomain.CurrentDomain.BaseDirectory,
ContentRootFileProvider = new PhysicalFileProvider(AppDomain.CurrentDomain.BaseDirectory)
};
var config = new ConfigurationBuilder();
var configured = Configure(config, env);
return configured.Build();
}
}
}
对于使用 .NET Core 2.1.0+ 和 Microsoft.Extensions.Hosting 来托管您的控制台应用程序的用户,您可以使用以下代码(根据 Feiyu Zhou 在另一个线程中的 ):
var hostBuilder = new HostBuilder()
.ConfigureHostConfiguration(config =>
{
if (args != null)
{
// enviroment from command line
// e.g.: dotnet run --environment "Staging"
config.AddCommandLine(args);
}
})
.ConfigureAppConfiguration((context, builder) =>
{
builder.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false)
.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true);
})
它是这样的,对于 dotnet 2.x 核心控制台应用程序:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
[...]
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
var serviceProvider = new ServiceCollection()
.AddLogging(options => options.AddConfiguration(configuration).AddConsole())
.AddSingleton<IConfiguration>(configuration)
.AddSingleton<SomeService>()
.BuildServiceProvider();
[...]
await serviceProvider.GetService<SomeService>().Start();
您可以在 SomeService
.
中注入 ILoggerFactory、IConfiguration
如果像我一样,您只是想为发布和开发模式使用不同的配置文件,只需添加一个 appsettings.Development.json 文件,并将文件的 属性 中的 CopyToOutputDirectory 设置设置为 true window.
现在,要根据构建配置访问文件,您可以使用 #if DEBUG preprocessor directive。
这是一个例子:
static void Main(string[] args)
{
#if DEBUG
var builder = new ConfigurationBuilder()
.AddJsonFile($"appsettings.Development.json", true, true);
#else
var builder = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json", true, true);
#endif
var configuration = builder.Build();
// ... use configuration
}
这些环境方面的事情似乎对大多数人都有效,但我完全不同意所有环境管理。 运行时间和目标系统都不知道它是什么。只有您,作为开发人员或部署机制,才知道目标系统是什么。
每个人都在谈论 ASPNETCORE_ENVIRONMENT 变量,甚至像这里 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-3.0 这样的官方文档也是如此。但实际上必须有人明确定义一个系统作为生产系统,例如,通过手动设置 ASPNETCORE_ENVIRONMENT 一次。你真的想假设并依赖它已经在你使用的每个环境中设置了吗?不,你不能。如果您必须将控制台应用程序部署到没有网站 运行ning 的批处理服务器怎么办? ASPNETCORE_ENVIRONMENT 不可用。如果您需要在没有 IIS 的情况下仅使用 kestrel 部署和 运行 一个 .net 核心 webapi 怎么办?没有 web.config 也没有环境变量。您希望您的 admins/operation 团队为您的控制台应用程序设置这个误导性变量吗?在这种情况下,我看到很多项目每个项目都有这样的应用程序设置:
appsettings.json
appsettings.development.json
appsettings.test.json
appsettings.uat.json
appsettings.staging.json
appsettings.production.json
请记住,默认情况下,这些文件中的每一个都将发布并部署到目标系统。乍一看,让环境 "decide" 应该使用哪个配置看起来很容易。但是您在不适合它的系统上部署了配置和可能的凭据。
结论
我推荐appsettings.json + appsettings.release.json。第一个仅适用于开发人员。改变它,随心所欲地玩它。最后一个是准备部署的 VALID 配置(过程)。在部署开始之前,转换配置以便为目标系统做好准备。而已。无需依赖目标机器上的设置,没有混乱的配置。即使服务器快速变化(如一般扩展、虚拟机、云等),也能完全控制您的应用程序
我感谢建设性的反馈:-)
对于 .NetCore 3.1 和使用 .CreateDefaultBuilder(args) 扩展的任何人。只需将 -environment "Development" 添加到调试设置中的命令行参数即可。完成。
从 Net Core 3.1++ 开始,通用主机 class Microsoft.Extensions.Hosting.Host 使用 DOTNET_ENVIRONMENT 环境变量而不是 ASPNETCORE_ENVIRONMENT。
在项目调试设置中设置 DOTNET_ENVIRONMENT="Development"
无需任何额外编码即可工作。
或者您可以像这样添加自己的前缀:
// works for WPF but should work similar for Console Apps
public partial class App : Application
{
private readonly IHost _host;
public App()
{
_host = Host.CreateDefaultBuilder()
.ConfigureHostConfiguration(configHost => {
configHost.AddEnvironmentVariables(prefix: "PREFIX_");
})
.ConfigureServices((context, services) =>
{
ConfigureServices(context.Configuration, services);
})
.Build();
}
private void ConfigureServices(
IConfiguration configuration,
IServiceCollection services)
{
// ...
}
// ...
}
我有一个 .NET Core 1.0.0 控制台应用程序和两个环境。我需要能够根据我在 运行 时设置的环境变量使用 appSettings.dev.json
和 appSettings.test.json
。通过依赖注入和 IHostingEnvironment 以及 EnvironmentName env,这对于 ASP.NET 核心 Web 应用程序来说似乎非常简单。变量,但是我应该如何为控制台应用程序连接(除了编写我自己的使用 Microsoft.Framework.Configuration.EnvironmentVariables
的自定义代码)?
谢谢。
我们在 .netcore
控制台应用程序中就是这样做的。这里的关键是在你的项目中包含正确的 dependencies(可能不是全部,根据你的需要检查)和复制到输出 appSetting.json 作为你的 buildoptions
{
"buildOptions": {
"emitEntryPoint": true,
"copyToOutput": {
"include": [
"appsettings*.json",
"App*.config"
]
}
},
using Microsoft.Extensions.Configuration;
namespace MyApp
{
public static void Main(string[] args)
{
var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var builder = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json", true, true)
.AddJsonFile($"appsettings.{environmentName}.json", true, true)
.AddEnvironmentVariables();
var configuration = builder.Build();
var myConnString= configuration.GetConnectionString("SQLConn");
}
}
您可以为 ASP.Net 核心环境变量 (ASPNETCORE_ENVIRONMENT) 执行此操作:-
using Microsoft.AspNetCore.Hosting;
using System;
public class Program {
private static string HostingEnvironment => Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
private static bool IsEnvironment(string environmentName) => HostingEnvironment?.ToLower() == environmentName?.ToLower() && null != environmentName;
private static bool Development => IsEnvironment(EnvironmentName.Development);
private static bool Production => IsEnvironment(EnvironmentName.Production);
private static bool Staging => IsEnvironment(EnvironmentName.Staging);
public static void Main(string[] args) { // Your code here }
}
然后你可以简单地使用 属性
public static void Main(string[] args) {
if (Development){
// Blow up the planet
}
}
您应该使用两个 IHostingEnvironment
接口。一个用于 ASP.NET 核心应用程序,另一个用于 .NET Core 控制台应用程序。您可以将此代码示例用于两者:
using System;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting.Internal;
namespace MyApplication.Common
{
public static class ConfigurationFactory
{
/// <summary>
/// Use for ASP.NET Core Web applications.
/// </summary>
/// <param name="config"></param>
/// <param name="env"></param>
/// <returns></returns>
public static IConfigurationBuilder Configure(IConfigurationBuilder config, IHostingEnvironment env)
{
return Configure(config, env.EnvironmentName);
}
/// <summary>
/// Use for .NET Core Console applications.
/// </summary>
/// <param name="config"></param>
/// <param name="env"></param>
/// <returns></returns>
private static IConfigurationBuilder Configure(IConfigurationBuilder config, Microsoft.Extensions.Hosting.IHostingEnvironment env)
{
return Configure(config, env.EnvironmentName);
}
private static IConfigurationBuilder Configure(IConfigurationBuilder config, string environmentName)
{
return config
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{environmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
}
/// <summary>
/// Use for .NET Core Console applications.
/// </summary>
/// <returns></returns>
public static IConfiguration CreateConfiguration()
{
var env = new HostingEnvironment
{
EnvironmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production",
ApplicationName = AppDomain.CurrentDomain.FriendlyName,
ContentRootPath = AppDomain.CurrentDomain.BaseDirectory,
ContentRootFileProvider = new PhysicalFileProvider(AppDomain.CurrentDomain.BaseDirectory)
};
var config = new ConfigurationBuilder();
var configured = Configure(config, env);
return configured.Build();
}
}
}
对于使用 .NET Core 2.1.0+ 和 Microsoft.Extensions.Hosting 来托管您的控制台应用程序的用户,您可以使用以下代码(根据 Feiyu Zhou 在另一个线程中的
var hostBuilder = new HostBuilder()
.ConfigureHostConfiguration(config =>
{
if (args != null)
{
// enviroment from command line
// e.g.: dotnet run --environment "Staging"
config.AddCommandLine(args);
}
})
.ConfigureAppConfiguration((context, builder) =>
{
builder.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false)
.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true);
})
它是这样的,对于 dotnet 2.x 核心控制台应用程序:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
[...]
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
var serviceProvider = new ServiceCollection()
.AddLogging(options => options.AddConfiguration(configuration).AddConsole())
.AddSingleton<IConfiguration>(configuration)
.AddSingleton<SomeService>()
.BuildServiceProvider();
[...]
await serviceProvider.GetService<SomeService>().Start();
您可以在 SomeService
.
如果像我一样,您只是想为发布和开发模式使用不同的配置文件,只需添加一个 appsettings.Development.json 文件,并将文件的 属性 中的 CopyToOutputDirectory 设置设置为 true window.
现在,要根据构建配置访问文件,您可以使用 #if DEBUG preprocessor directive。
这是一个例子:
static void Main(string[] args)
{
#if DEBUG
var builder = new ConfigurationBuilder()
.AddJsonFile($"appsettings.Development.json", true, true);
#else
var builder = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json", true, true);
#endif
var configuration = builder.Build();
// ... use configuration
}
这些环境方面的事情似乎对大多数人都有效,但我完全不同意所有环境管理。 运行时间和目标系统都不知道它是什么。只有您,作为开发人员或部署机制,才知道目标系统是什么。
每个人都在谈论 ASPNETCORE_ENVIRONMENT 变量,甚至像这里 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-3.0 这样的官方文档也是如此。但实际上必须有人明确定义一个系统作为生产系统,例如,通过手动设置 ASPNETCORE_ENVIRONMENT 一次。你真的想假设并依赖它已经在你使用的每个环境中设置了吗?不,你不能。如果您必须将控制台应用程序部署到没有网站 运行ning 的批处理服务器怎么办? ASPNETCORE_ENVIRONMENT 不可用。如果您需要在没有 IIS 的情况下仅使用 kestrel 部署和 运行 一个 .net 核心 webapi 怎么办?没有 web.config 也没有环境变量。您希望您的 admins/operation 团队为您的控制台应用程序设置这个误导性变量吗?在这种情况下,我看到很多项目每个项目都有这样的应用程序设置:
appsettings.json
appsettings.development.json
appsettings.test.json
appsettings.uat.json
appsettings.staging.json
appsettings.production.json
请记住,默认情况下,这些文件中的每一个都将发布并部署到目标系统。乍一看,让环境 "decide" 应该使用哪个配置看起来很容易。但是您在不适合它的系统上部署了配置和可能的凭据。
结论
我推荐appsettings.json + appsettings.release.json。第一个仅适用于开发人员。改变它,随心所欲地玩它。最后一个是准备部署的 VALID 配置(过程)。在部署开始之前,转换配置以便为目标系统做好准备。而已。无需依赖目标机器上的设置,没有混乱的配置。即使服务器快速变化(如一般扩展、虚拟机、云等),也能完全控制您的应用程序
我感谢建设性的反馈:-)
对于 .NetCore 3.1 和使用 .CreateDefaultBuilder(args) 扩展的任何人。只需将 -environment "Development" 添加到调试设置中的命令行参数即可。完成。
从 Net Core 3.1++ 开始,通用主机 class Microsoft.Extensions.Hosting.Host 使用 DOTNET_ENVIRONMENT 环境变量而不是 ASPNETCORE_ENVIRONMENT。
在项目调试设置中设置 DOTNET_ENVIRONMENT="Development"
无需任何额外编码即可工作。
或者您可以像这样添加自己的前缀:
// works for WPF but should work similar for Console Apps
public partial class App : Application
{
private readonly IHost _host;
public App()
{
_host = Host.CreateDefaultBuilder()
.ConfigureHostConfiguration(configHost => {
configHost.AddEnvironmentVariables(prefix: "PREFIX_");
})
.ConfigureServices((context, services) =>
{
ConfigureServices(context.Configuration, services);
})
.Build();
}
private void ConfigureServices(
IConfiguration configuration,
IServiceCollection services)
{
// ...
}
// ...
}