.NET Core控制台应用程序,如何根据环境配置appSettings?

103
我有一个.NET Core 1.0.0控制台应用程序和两个环境。我需要能够根据我在运行时设置的环境变量使用appSettings.dev.jsonappSettings.test.json。这对于ASP.NET Core web应用程序来说似乎非常直截了当,通过依赖注入、IHostingEnvironment和EnvironmentName环境变量进行,但是对于控制台应用程序,除了编写自己的自定义代码使用Microsoft.Framework.Configuration.EnvironmentVariables之外,我该如何连接它们呢?谢谢。
12个回答

135

这就是我们在.netcore控制台应用程序中的做法。关键在于确保在项目中包含正确的依赖项 (可能不是全部,根据您的需要进行检查),并且将appSetting.json作为生成选项的一部分复制到输出目录

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

8
谢谢。我最终使用了更加复杂的方法,使用new ConfigurationBuilder().AddEnvironmentVariables() 创建了配置构建器,并找到了 ASPNETCORE_ENVIRONMENT 变量。 - user2916547
3
жҲ‘и®ӨдёәдҪ еә”иҜҘж·»еҠ дёҖдёӘNuGetеҢ…Microsoft.Extensions.Configuration.Jsonпјҡhttps://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.0&tabs=basicconfiguration#json-configuration - Junior Mayhé
3
不引用Microsoft.AspNetCore.Hosting,如何使Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")工作? - HaBo
5
有了新的 csproj 结构,你需要这样做: <ItemGroup> <None Update="appsettings*.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup> 这段代码是用来将 "appsettings*.json" 文件复制到输出目录并保留最新版本的。 - Thulani Chivandikwa
2
请更新您的答案。显然,在您的代码示例中,json部分不需要。 - Akmal Salikhov
显示剩余8条评论

33

自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)
    {
       // ...
    }

    // ...
}

30

如果您正在使用.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);
    })

10

你应该使用两个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();
        }
    }
}

1
控制台应用程序“version”命名空间为“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
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
2
这个答案需要更新,因为它目前使用了已弃用的代码。你应该删除 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) - Arvo Bowen
显示剩余3条评论

9

如果和我一样,你只是想为发布模式和开发模式使用不同的配置文件,只需在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
}

4
这不是一个好的解决方案,因为它可能隐藏编译错误。一旦你推到构建服务器上并且指令变成真/假,这些错误就会显现出来。更好的方法是使用环境变量。我不是在评判你 - 我自己过去也经常这么做,只是我遇到过几次我提到的问题。 - jcvandan
2
我建议您始终添加appsettings.json文件(解决@jcvandan从未加载它的问题),并且#if DEBUG 加载appsettings.Development.json - 标准方式是允许开发环境覆盖设置(如果需要),而不必指定所有设置。 - oatsoda
1
#if DEBUG 是我使用的方式,但只是为了将环境变量设置为 Development 或默认情况下的 Production。我发现对于控制台应用程序,Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") 总是返回 Production,除非您使用 launchSettings.json 文件(或其他更深层次的调整),这些解决方案都没有提到。使用默认的 VS 模板和默认的控制台应用程序模板,这是唯一的解决方案,可以简单地拥有一个没有额外配置的开发环境。 - Sum None

3

这些环境设置似乎适用于大多数人,但我完全不同意所有的环境管理。无论运行时还是目标系统都不知道它是什么。只有你作为开发者或部署机制知道目标系统是什么。

每个人都在谈论ASPNETCORE_ENVIRONMENT变量,甚至官方文档也是如此,例如这里。但实际上,必须有人明确地将一个系统定义为生产系统,例如通过手动设置ASPNETCORE_ENVIRONMENT一次。你真的想假定并依赖于它,认为这已经在你使用的每个环境中设置了吗?不,你不能。如果你需要将控制台应用程序部署到没有运行任何网站的批处理服务器上怎么办?ASPNETCORE_ENVIRONMENT不可用。如果你需要部署和运行一个没有IIS, 仅使用Kestrel的 .net core webapi 呢?没有web.config和环境变量。你希望你的管理员/操作团队为你的控制台应用程序设置这个误导性的变量吗?在这种情况下,我看到很多项目每个项目都有类似以下的appsettings:

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

请注意,默认情况下,这些文件都将被发布并部署到目标系统。乍一看,让环境“决定”使用哪个配置似乎很容易。但是,您已经在不打算用于此的系统上部署了配置和凭据。
结论:
我建议使用appsettings.json + appsettings.release.json。第一个仅用于dev。随意更改它,玩弄它。最后一个是一个有效的配置,可以直接部署(process)。在部署开始之前,将配置转换为目标系统所需的状态。如此简单。无需依赖目标计算机上的设置,也无需混乱的配置。即使服务器快速更改(比如总体缩放,VM,云等),也可以完全控制应用程序。感谢建设性的反馈 :-)

1
你有点误解了,是的,条件可以通过配置值而不是环境变量来确定。我在Web API中使用swagger来让开发人员检查和测试端点时,应用程序的行为不同。 通过将相同的二进制文件推广到生产环境的一致的发布管理流程,需要切换此功能。无论是通过每个应用程序/环境的配置设置实现还是通过单个环境变量实现都无关紧要,但环境设置适用于同一服务器上的所有应用程序,而不是应用程序配置。 - Antony Booth
没有人必须明确地将系统定义为生产系统,因为这是默认设置。 但是,作为开发人员,您可以将自己的系统定义为开发环境,并使用*.development.json文件中的设置覆盖默认的生产设置。 - Merilix2

2

如果你正在使用.NetCore 3.1并且使用.CreateDefaultBuilder(args)扩展,只需在调试设置中将-environment“Development”添加到命令行参数中即可。完成。


2

对于一个dotnet 2.x core控制台应用程序,类似于这样:

最初的回答:

        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。"Original Answer"翻译成"最初的回答"。

1
根据文档,这些都是由默认的主机构建器自动提供的。唯一需要的代码是使用默认构建器来包含基于环境、命令行参数、环境变量、用户机密(仅适用于开发环境)等正确的appsettings文件。
IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =>
    {
        // configure services here
    })
    .Build();

host.Run();

关键是使用CreateDefaultBuilder()方法,该方法预配置了所有这些源。您还可以使用流畅的API添加其他源,例如内存集合,这将优先于前面提到的源。
来源:

.NET通用主机

Host.CreateDefaultBuilder()方法


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

8
问题不是关于 ASP.NET Core。 - Miklós Tóth
1
我知道,但是与asp.net core相关的唯一事情是环境变量的名称和用于获取“Development”、“Staging”和“Production”字符串常量的.net core库。我认为使用一个合法的环境变量而不是我自己编造的一个会很有用。它可以是任何东西,甚至不在asp.net core应用程序中。 - Antony Booth
1
这个(以及它的同级)更多地是“非asp.net(core)”风格的吗?https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.environmentname.development - granadaCoder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接