【问题标题】:Automatically set appsettings.json for dev and release environments in asp.net core?为asp.net核心中的开发和发布环境自动设置appsettings.json?
【发布时间】:2018-03-04 00:11:42
【问题描述】:

我在appsettings.json 中为数据库连接字符串、webapi 位置等定义了一些值,这些值对于开发、暂存和实时环境是不同的。

有没有办法拥有多个appsettings.json 文件(如appsettings.live.json 等)并让asp.net 应用程序根据其运行的构建配置“知道”使用哪个文件?

【问题讨论】:

    标签: c# asp.net-core appsettings


    【解决方案1】:

    当我使用没有网页的控制台应用程序时,这是适用于我的版本:

    var builder = new ConfigurationBuilder()
                 .SetBasePath(Directory.GetCurrentDirectory())
                 .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                 .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true);
    
                IConfigurationRoot configuration = builder.Build();
                AppSettings appSettings = new AppSettings();
                configuration.GetSection("AppSettings").Bind(appSettings);
    

    【讨论】:

      【解决方案2】:

      .vscode/launch.json 文件仅由 Visual Studio 以及 /Properties/launchSettings.json 文件使用。不要在生产中使用这些文件。

      launchSettings.json 文件:

      1. 仅在本地开发机器上使用。
      2. 未部署。
      3. 包含配置文件设置。

        • launchSettings.json 中设置的环境值覆盖系统环境中设置的值

      以使用文件“appSettings.QA.json”为例。您可以使用“ASPNETCORE_ENVIRONMENT”。请按照以下步骤操作。

      1. 在主机上添加一个新的环境变量并将其命名为“ASPNETCORE_ENVIRONMENT”。将其值设置为“QA”。
      2. 在您的项目中创建一个文件“appSettings.QA.json”。在此处添加您的配置。
      3. 在步骤 1 中部署到机器。确认已部署“appSettings.QA.json”。
      4. 加载您的网站。预计 appSettings.QA.json 将在此处使用。

      【讨论】:

      • 这是否意味着,如果您有 5 个环境和 5 个 appsettings.EnvName.json 文件,所有这些都将被部署并且只有一台选定的机器,因为构建定义的工件将包含所有 5 个文件?或者只应该部署 appsettings.json(作为主要)+ appsettings.CurrentEnvironment.json(作为覆盖)以及如何部署?
      【解决方案3】:

      .NET Core 3.0+ 更新

      1. 您可以使用CreateDefaultBuilder,它会自动构建配置对象并将其传递给您的启动类:

        WebHost.CreateDefaultBuilder(args).UseStartup<Startup>();
        
        public class Startup
        {
            public Startup(IConfiguration configuration) // automatically injected
            {
                Configuration = configuration;
            }
            public IConfiguration Configuration { get; }
            /* ... */
        }
        
      2. CreateDefaultBuilder 自动包含适当的 appsettings.<i>Environment</i>.json 文件,因此为每个环境添加单独的 appsettings 文件:

      3. 然后在运行/调试时设置ASPNETCORE_ENVIRONMENT环境变量

      如何设置环境变量

      根据您的 IDE,dotnet 项目通常会在几个地方查找环境变量:

      • 对于 Visual Studio,请转到项目 > 属性 > 调试 > 环境变量:

      • 对于 Visual Studio 代码,编辑 .vscode/launch.json > env

      • 使用启动设置,编辑Properties/launchSettings.json > environmentVariables

        也可以从 Visual Studio 的工具栏中选择

      • 使用 dotnet CLI,为 setting environment variables per your OS 使用适当的语法

        注意:当使用dotnet run 启动应用程序时,会读取launchSettings.json(如果可用),并且launchSettings.json 中的environmentVariables 设置会覆盖环境变量。

      Host.CreateDefaultBuilder 是如何工作的?

      .NET Core 3.0 在平台扩展下添加了Host.CreateDefaultBuilder,它将提供IConfiguration 的默认初始化,它按以下顺序为应用提供默认配置:

      1. appsettings.json 使用 JSON configuration provider
      2. appsettings.<i>Environment</i>.json 使用 JSON configuration provider。例如:
        • appsettings.<i>Production</i>.json
        • appsettings.<i>Development</i>.json
      3. App secrets 当应用在开发环境中运行时。
      4. 环境变量使用Environment Variables configuration provider
      5. 命令行参数使用Command-line configuration provider

      进一步阅读 - MS Docs

      【讨论】:

      • 谢谢,很好,但是如何使用控制台进程(或工作进程模板/脚手架)来做到这一点?
      • 这不适用于最新版本,它将始终采用 appsettings.json 并忽略 appsettings.development.json。 Run (dev) 和 run (prod) 也不见了。
      • 这应该是公认的答案。
      【解决方案4】:

      在 ASP.NET Core 中,您应该使用环境变量而不是构建配置以获得正确的 appsettings.json

      1. 右键单击您的项目>属性>调试>环境变量

      2. ASP.NET Core 将使用适当的 appsettings.json 文件:

      3. 现在您可以像这样使用该环境变量:

        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();
        
            Configuration = builder.Build();
        }
        

      注意:如果您使用@Dmitry's answer,您可能会遇到问题,例如。 在 Azure 上覆盖 appsettings.json 值时。

      【讨论】:

        【解决方案5】:

        我添加了工作环境的屏幕截图,因为它花费了我几个小时的研发时间。

        1. 首先,在您的launch.json 文件中添加一个密钥。

          请看下面的截图,我已经添加了 Development 作为我的环境。

        2. 然后,在您的项目中,创建一个包含环境名称的新 appsettings.{environment}.json 文件。

          在以下屏幕截图中,查找两个具有不同名称的文件:

          • appsettings.Development.Json
          • appSetting.json


        3. 最后,将它配置到您的 StartUp 类中,如下所示:

          public Startup(IHostingEnvironment env)
          {
              var builder = new ConfigurationBuilder()
                  .SetBasePath(env.ContentRootPath)
                  .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                  .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                  .AddEnvironmentVariables();
          
              Configuration = builder.Build();
          }
          
        4. 最后,你可以像这样从命令行运行它:

          dotnet run --environment "Development"
          

          其中 "Development" 是我的环境的名称。

        【讨论】:

        • 试过了,效果很好。 VS2017 甚至在基础文件下显示不同的版本。赞成票。
        • 当 ihostingenvironment 被弃用时,你如何在 core 2.2 中做到这一点
        • @djack109 你应该改用IWebHostEnvironment
        【解决方案6】:
        1. 创建多个appSettings.<i>$(Configuration)</i>.json 文件,例如:

          • appSettings.staging.json
          • appSettings.production.json
        2. 在项目上创建一个预构建事件,将相应的文件复制到appSettings.json

          copy appSettings.$(Configuration).json appSettings.json
          
        3. 在您的配置生成器中仅使用 appSettings.json

          var builder = new ConfigurationBuilder()
                      .SetBasePath(env.ContentRootPath)
                      .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                      .AddEnvironmentVariables();
          
          Configuration = builder.Build();
          

        【讨论】:

        • 这应该是一个可以接受的答案。复杂情况可以使用SlowCheetah
        • 如何在项目上创建预构建事件?该行的起始副本应该放在哪里......实际上应该放在哪里?
        • @Paul 在 Visual Studio 中,右键单击解决方案资源管理器视图中的项目,从右键菜单中选择 Properties,然后在属性视图中选择 Build Events
        【解决方案7】:

        您可以在launchSettings.json 中添加配置名称为ASPNETCORE_ENVIRONMENT,如下所示

          "iisSettings": {
            "windowsAuthentication": false,
            "anonymousAuthentication": true,
            "iisExpress": {
              "applicationUrl": "http://localhost:58446/",
              "sslPort": 0
            }
          },
          "profiles": {
            "IIS Express": {
              "commandName": "IISExpress",
              "environmentVariables": {
                ASPNETCORE_ENVIRONMENT": "$(Configuration)"
              }
            }
          }
        

        【讨论】:

          【解决方案8】:

          你可以使用条件编译:

          public Startup(IHostingEnvironment env)
          {
              var builder = new ConfigurationBuilder()
              .SetBasePath(env.ContentRootPath)
              .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
          #if SOME_BUILD_FLAG_A
              .AddJsonFile($"appsettings.flag_a.json", optional: true)
          #else
              .AddJsonFile($"appsettings.no_flag_a.json", optional: true)
          #endif
              .AddEnvironmentVariables();
              this.configuration = builder.Build();
          }
          

          【讨论】:

          • 您应该在 MSBuild/TFS 构建中设置环境变量。条件编译会导致 CI​​ 构建中容易处理的错误。即 .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
          • 环境变量见我的回答 (stackoverflow.com/a/50331886/1319086)
          • 这种方法强制为每个环境专门重新编译代码,使其无法重新分发/安装到其他地方。
          • 问题是关于“了解构建配置”
          • 这不应被标记为已接受的答案 - 尽管这是一个解决方案,但它不是最佳实践。
          【解决方案9】:

          只是针对.NET core 2.0用户的更新,可以在调用CreateDefaultBuilder后指定应用配置:

          public class Program
          {
             public static void Main(string[] args)
             {
                BuildWebHost(args).Run();
             }
          
             public static IWebHost BuildWebHost(string[] args) =>
                WebHost.CreateDefaultBuilder(args)
                       .ConfigureAppConfiguration(ConfigConfiguration)
                       .UseStartup<Startup>()
                       .Build();
          
             static void ConfigConfiguration(WebHostBuilderContext ctx, IConfigurationBuilder config)
             {
                      config.SetBasePath(Directory.GetCurrentDirectory())
                          .AddJsonFile("config.json", optional: false, reloadOnChange: true)
                          .AddJsonFile($"config.{ctx.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true);
          
             }
           }
          

          【讨论】:

          • 如何在使用的环境之间切换?是否应该在任何配置文件中进行更改?我知道我需要将项目在 Azure 上运行时要使用的 URL 添加到 appsettings.json 并将本地运行时要执行的 URL(按 F5)添加到 appsettings.Development.json。那是对的吗?我要使用的字符串在文件 launchSettings.json 中,我有点不清楚如何根据应用程序的执行位置(或者是否应该在全部)。
          • @DonkeyBanana 环境只不过是项目属性中指定的设置。在 VS 2017 中,右键单击项目 > 属性。在调试下,您将看到密钥 ASPNETCORE_ENVIRONMENT 的当前环境。该值将替换为ctx.HostingEnvironment.EnvironmentName}。因此,如果您在属性中将该值设置为“生产”,项目将在根文件夹中查找config.Production.json 文件。欲了解更多信息,请查看此link
          • 在 WebHost.CreateDefaultBuiler(... 中创建一个Error CS0266 Cannot implicitly convert type 'Microsoft.AspNetCore.Hosting.IWebHost' to 'Microsoft.AspNetCore.Hosting.IWebHostBuilder'. An explicit conversion exists (are you missing a cast?)
          • 值得注意的是,here 指出“当您使用 CreateDefaultBuilder 初始化新的主机构建器时,会自动调用两次 AddJsonFile”。换句话说,它已经在加载 appSettings.json,然后根据您的环境配置,它正在加载 appsettings.{Environment}.json
          • @umutsen 在最新的 Visual Studio 中没有更多的运行环境设置
          【解决方案10】:

          您可以像这样在Startup 构造函数中使用环境变量和ConfigurationBuilder 类:

          public Startup(IHostingEnvironment env)
          {
              var builder = new ConfigurationBuilder()
              .SetBasePath(env.ContentRootPath)
              .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
              .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
              .AddEnvironmentVariables();
              this.configuration = builder.Build();
          }
          

          然后您为您需要的每个环境创建一个appsettings.xxx.json 文件,其中“xxx”是环境名称。请注意,您可以将所有全局配置值放入“普通”appsettings.json 文件中,并且仅将环境特定的内容放入这些新文件中。

          现在您只需要一个名为ASPNETCORE_ENVIRONMENT 的环境变量,并带有一些特定的环境值(“live”、“staging”、“production”等)。您可以在开发环境的项目设置中指定此变量,当然您还需要在暂存和生产环境中进行设置。你在那里做的方式取决于这是什么样的环境。

          更新:我刚刚意识到您想根据您当前的构建配置选择appsettings.xxx.json。我提出的解决方案无法实现这一点,我不知道是否有办法做到这一点。然而,“环境变量”方式是可行的,并且可能是您的方法的一个很好的替代方案。

          【讨论】:

          • 我在项目属性->调试部分中查看了使用环境变量,但是没有明显的方法将如何根据项目设置进行更改。那是我可以添加到我的项目中来处理它的另一个文件吗?
          • 在项目属性中设置变量仅适用于在您的开发环境(可能是 Visual Studio)中使用它。您需要根据特定环境(IIS、Azure)为您部署的应用程序在其他地方设置它。我不建议在某个配置文件中设置该变量,因为该文件也可能被部署,然后覆盖服务器值。
          • 您在构建配置中设置它。如果没有构建配置文件,那么他们是手动进行的,因此他们需要在(过时的)部署配置文件中进行设置
          • 我在 Azure 中有多个环境,例如测试、登台和生产。如果我想将 Web 应用的发布版本从 VS 发布到 Azure,我应该在哪里更改 ASPNETCORE_ENVIRONMENT 变量?
          • 我们在部署过程中不会更改变量,而是内置在特定环境中。在 Azure 中,您可以直接在“应用程序设置”下的应用服务配置中设置这些值。如果您使用多个插槽,请不要忘记将它们标记为“部署插槽设置”。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-05-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-22
          相关资源
          最近更新 更多