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


74

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

谢谢。

Answers:


98

这就是我们在.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");
    }

}


4
谢谢。我最终使用了一个更复杂的版本,即使用new ConfigurationBuilder().AddEnvironmentVariables()和查找ASPNETCORE_ENVIRONMENT
user2916547 '16

1
我想你应该添加的NuGet Microsoft.Extensions.Configuration.JsonNuGet包:docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/...
少年Mayhé

2
不参考Microsoft.AspNetCore.Hosting,此Environment.GetEnvironmentVariable(“ ASPNETCORE_ENVIRONMENT”)将如何工作?
HaBo

2
使用新的csproj结构,您将<ItemGroup> <None Update =“ appsettings * .json”> <CopyToOutputDirectory> PreserveNewest </ CopyToOutputDirectory> </ None> </ ItemGroup>
Thulani Chivandikwa

1
请更新您的答案。显然您的代码示例中的json部分没有必要...
Akmal Salikhov

18

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

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

9

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"),
                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();
        }
    }
}

1
控制台应用程序“版本”名称空间“ Microsoft.Extensions.Hosting”,接口“ IHostingEnvironment”,程序集文件:“ microsoft.extensions.hosting.abstractions \ 2.1.1 \ lib \ netstandard2.0 \ Microsoft.Extensions.Hosting.Abstractions.dll “
granadaCoder

1
这是我必须添加才能使此代码正常工作的nuget软件包的列表。<PackageReference I =“ Microsoft.AspNetCore.Hosting.Abstractions” Version =“ 2.1.1” /> <PackageReference I =“ Microsoft.Extensions.Configuration” Version =“ 2.1.1” /> <PackageReference Include =“ Microsoft.Extensions .Configuration.EnvironmentVariables“ Version =” 2.1.1“ /> <PackageReference I =” Microsoft.Extensions.Configuration.Json“ Version =” 2.1.1“ /> <PackageReference I =” Microsoft.Extensions.Hosting“ Version =” 2.1.1“ /> <PackageReference I =” Microsoft.Extensions.Hosting.Abstractions“ Version =” 2.1.1“ />
granadaCoder

是否应该在控制台应用程序项目中创建Microsoft.AspNetCore命名空间的依赖项?
拉斐尔

1
<Project Sdk =“ Microsoft.NET.Sdk”> <PropertyGroup> <TargetFramework> netcoreapp3.1 </ TargetFramework> </ PropertyGroup> <ItemGroup> <PackageReference Include =“ Microsoft.Extensions.Configuration” Version =“ 3.1.0” /> <PackageReference Include =“ Microsoft.Extensions.Configuration.EnvironmentVariables” Version =“ 3.1.0” /> <PackageReference Include =“ Microsoft.Extensions.Configuration.Json” Version =“ 3.1.0” /> <PackageReference Include = “ Microsoft.Extensions.Hosting” Version =“ 3.1.0” />
granadaCoder

1
</ ItemGroup> <ItemGroup> <FrameworkReference Include =“ Microsoft.AspNetCore.App” /> </ ItemGroup> </ Project>
granadaCoder

4

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

每个人都在谈论ASPNETCORE_ENVIRONMENT变量,甚至像此处的官方文档https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-3.0。但是实际上,有人必须将系统明确定义为生产系统,例如,只需手动设置一次ASPNETCORE_ENVIRONMENT。您是否真的要假设并依靠它在您使用的每个环境中都已设置?不,你不能。如果必须将控制台应用程序部署到没有网站运行的批处理服务器上怎么办?ASPNETCORE_ENVIRONMENT不可用。如果您需要仅使用kestrel来部署和运行不带IIS的.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中使用不同的应用程序行为,在该行为中,开发人员会用招摇过头来检查和测试端点。具有一致的发布管理流程,可以将相同的二进制文件升级到生产环境,因此需要切换此功能。是否通过每个应用程序/环境的配置设置来实现,还是单个环境变量都无关紧要,只是环境设置适用于同一服务器上的所有应用程序,与应用程序配置不同。
安东尼·布斯,

3

您可以对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
        }
    }

4
问题不在于asp.net核心。
米克洛什·托特

1
我知道,但是与asp.net核心远程相关的唯一事情是环境变量的名称和.net核心库,用于获取'Development','Staging'和'Production'的字符串常量。我认为使用合法的环境变量代替我编写的变量将很有用。它可以是任何东西,而根本不在asp.net核心应用程序中。
安东尼·布斯,

1
这(及其兄弟姐妹)是否更多是“ NON asp.net(核心)”'ish? docs.microsoft.com/en-us/dotnet/api/…–
granadaCoder

3

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

现在,要根据构建配置访问文件,可以使用#if DEBUG预处理程序指令

这是一个例子:

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
}

1
这是一个糟糕的解决方案,因为它可以隐藏编译错误,当您推送到构建服务器并且指令变为true / false时,该错误将变得显而易见。最好使用环境变量。我没有判断-我过去已经做过很多次,只是我遇到了我提到过几次的问题。
jcvandan

我建议您始终添加appsettings.json文件(解决@jcvandan从不加载的问题),并#if DEBUG 同时加载appsettings.Development.json-标准方法是允许开发人员在需要时覆盖设置,而不必全部指定。
oatsoda

2

对于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();

您可以在中注入ILoggerFactory,IConfiguration SomeService

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.