.NET Core 控制台应用程序,如何为每个环境配置 appSettings?

Posted

技术标签:

【中文标题】.NET Core 控制台应用程序,如何为每个环境配置 appSettings?【英文标题】:.NET Core console application, how to configure appSettings per environment? 【发布时间】:2017-01-27 04:00:20 【问题描述】:

我有一个 .NET Core 1.0.0 控制台应用程序和两个环境。我需要能够根据我在运行时设置的环境变量使用appSettings.dev.jsonappSettings.test.json。通过依赖注入和 IHostingEnvironment 以及 EnvironmentName env,这对于 ASP.NET Core Web 应用程序来说似乎非常简单。变量,但是我应该如何为控制台应用程序连接东西(除了编写我自己的使用Microsoft.Framework.Configuration.EnvironmentVariables 的自定义代码)?

谢谢。

【问题讨论】:

【参考方案1】:

这就是我们在.netcore 控制台应用程序中的操作方式。这里的关键是在您的项目中包含正确的依赖项可能不是全部,根据您的需要检查)和复制到输出 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");
    

【讨论】:

谢谢。我最终使用了一个更复杂的版本,使用new ConfigurationBuilder().AddEnvironmentVariables() 并找到ASPNETCORE_ENVIRONMENT 我认为你应该添加一个 nuget Microsoft.Extensions.Configuration.Json nuget 包:docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/… 如果不参考 Microsoft.AspNetCore.Hosting,这个 Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") 将如何工作? 使用新的 csproj 结构,您将 PreserveNewest 请更新您的答案。显然您的代码示例的 json 部分不需要...【参考方案2】:

对于使用 .NET Core 2.1.0+ 和 Microsoft.Extensions.Hosting 来托管您的控制台应用程序的用户,您可以使用以下代码(根据另一个线程中的飞宇周的answer):

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

【讨论】:

【参考方案3】:

您应该使用两个IHostingEnvironment 接口。一种用于 ASP.NET Core 应用程序,另一种用于 .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();
        
    

【讨论】:

控制台应用“版本”命名空间“Microsoft.Extensions.Hosting”,接口“IHostingEnvironment”,程序集文件:“microsoft.extensions.hosting.abstractions\2.1.1\lib\netstandard2.0\Microsoft .Extensions.Hosting.Abstractions.dll" 这是我必须添加的 nuget 包列表,以使此代码正常工作。 netcoreapp3.1 这个答案应该更新,因为它目前使用的是折旧代码。您应该删除using Microsoft.AspNetCore.Hosting; 语句并明确定义在这种情况下完全键入的新建议接口。 “用于 ASP.NET Core Web 应用程序。”:public static IConfigurationBuilder Configure(IConfigurationBuilder config, Microsoft.AspNetCore.Hosting.IWebHostEnvironment env) 和“用于 .NET Core 控制台应用程序。”:private static IConfigurationBuilder Configure(IConfigurationBuilder config, Microsoft.Extensions.Hosting.IHostEnvironment env)【参考方案4】:

从 Net Core 3.1++ 开始,通用主机类 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)
    
       // ...
    

    // ...

【讨论】:

【参考方案5】:

如果像我一样,您只是想为发布和开发模式使用不同的配置文件,只需在文件的属性窗口中添加一个将 CopyToOutputDirectory 设置设置为 true 的 appsettings.Development.json 文件。

现在,要根据构建配置访问文件,您可以使用#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

【讨论】:

这是一个糟糕的解决方案,因为它可以隐藏编译错误,一旦你推送到构建服务器并且指令变为真/假,这些错误就会变得明显。使用环境变量要好得多。不过我不是在评判——我过去已经做过很多次了,只是我遇到了我多次提到的问题。 我建议您总是添加appsettings.json文件(解决@jcvandan从不加载它的问题)和#if DEBUG 加载appsettings.Development.json - 标准方式是允许开发在需要时覆盖设置,而不必全部指定。【参考方案6】:

这些环境问题似乎对大多数人都有效,但我完全不同意所有的环境管理。运行时和目标系统是否知道它是什么。只有您作为开发人员或部署机制,才知道目标系统是什么。

每个人都在谈论 ASPNETCORE_ENVIRONMENT 变量,甚至像这里的官方文档https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-3.0。但实际上有人必须将系统明确定义为生产系统,例如,通过手动设置一次 ASPNETCORE_ENVIRONMENT 。您是否真的想假设并依赖它已经在您使用的每个环境中设置?不,你不能。如果您必须将控制台应用程序部署到没有网站运行的批处理服务器怎么办? ASPNETCORE_ENVIRONMENT 不可用。如果您需要在没有 IIS 的情况下仅使用 kestrel 部署和运行 .net 核心 webapi 怎么办?没有 web.config 也没有环境变量。您是否希望您的管理员/运营团队为您的控制台应用程序设置此误导性变量?在这种情况下,我看到很多项目每个项目都有这样的应用设置:

appsettings.json
appsettings.development.json
appsettings.test.json
appsettings.uat.json
appsettings.staging.json
appsettings.production.json

请记住,默认情况下,这些文件中的每一个都将发布并部署到目标系统。乍一看,让环境“决定”应该使用哪个配置看起来很容易。但是您在不适合它的系统上部署了配置和潜在的凭据。

结论

我推荐 appsettings.json + appsettings.release.json。第一个仅适用于开发人员。改变它,随心所欲地玩它。最后一个是准备好部署(过程)的有效配置。在部署开始之前,转换配置以准备好用于目标系统。而已。无需依赖目标机器上的设置,没有杂乱的配置。即使服务器快速变化(例如一般的扩展、VM、云等),也能完全控制您的应用

我很欣赏建设性的反馈:-)

【讨论】:

您有点忽略了这一点,是的,条件可以由配置值而不是环境变量来确定。我在 Web API 中有不同的应用程序行为,我使用 swagger 让开发人员检查和测试端点。具有将相同二进制文件提升到生产环境的一致发布管理流程,需要切换此功能。这是通过每个应用程序/环境的配置设置还是单个环境变量来实现的,这无关紧要,除非环境设置适用于同一服务器上的所有应用程序,这与应用程序配置不同。【参考方案7】:

对于 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。

【讨论】:

【参考方案8】:

适用于 .NetCore 3.1 和使用 .CreateDefaultBuilder(args) 扩展的任何人。只需将 -environment "Development" 添加到调试设置中的命令行参数即可。完成。

【讨论】:

【参考方案9】:

您可以对 ASP.Net Core 环境变量 (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
        
    

【讨论】:

问题与 asp.net core 无关。 我知道,但是与asp.net核心远程相关的唯一是环境变量的名称和用于获取字符串的.net核心库“开发”、“分期”和“生产”的常量。我认为使用合法的环境变量而不是我编造的环境变量会很有用。它可以是任何东西,根本不在 asp.net 核心应用程序中。 这个(及其兄弟姐妹)是否更“非 asp.net(核心)”? docs.microsoft.com/en-us/dotnet/api/…

以上是关于.NET Core 控制台应用程序,如何为每个环境配置 appSettings?的主要内容,如果未能解决你的问题,请参考以下文章