在 ASP.NET Core 2.1 中加载 appsettings.{envName}.json 文件

Load appsettings.{envName}.json file in ASP.NET Core 2.1

prior versions of ASP.NET Core中,我们可以为生产环境动态添加appsetting.json个环境后缀为appsettings.Production.json的文件。

由于结构有点不同,现在似乎已在 class Program 中加载了配置。但是我们这里没有注入``,所以我自己用环境变量试了一下:

public class Program {
        public static void Main(string[] args) {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) {
            string envName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
            string envConfigFile = $"appsettings.{envName}.json";

            var config = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile(envConfigFile, optional: true);

            var finalConfig = config.Build();
            return WebHost.CreateDefaultBuilder(args)
                .UseUrls("http://0.0.0.0:5000")
                .UseConfiguration(finalConfig)
                .UseStartup<Startup>();
        }
    }

代码已执行,但它不会覆盖我的 appsettings.json 配置。假设我有以下 appsettings.json:

{
    "MyConnectionString": "Server=xxx,Database=xxx, ..."
}

此 ConnectionString 正在运行。现在我创建appsettings.Development.json

{
    "MyConnectionString": ""
}

并设置ASPNETCORE_ENVIRONMENT=Development。这绝对应该抛出异常。但是应用程序使用来自 appsettings.json 的 ConnectionString 正确启动。

按照ASP.NET Core 2 configuration changes, the WebHost.CreateDefaultBuilder method should itself use the new ConfigureAppConfiguration approach and load environment specific config by default. Also the official docs的说法,appsettings.{Environment}.json是自动加载的。但这不起作用,像这样手动加载也不能解决问题:

return WebHost.CreateDefaultBuilder(args)
                .UseUrls("http://0.0.0.0:5000")
                .ConfigureAppConfiguration((builderContext, config) => {
                    IHostingEnvironment env = builderContext.HostingEnvironment;
                    config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
                })
                .UseStartup<Startup>();

如何使用 "appsettings.{envName}.json" 模式覆盖配置?我喜欢它,因为在 ASP.NET Core 中覆盖环境特定的东西很方便。

您应该检查您的构建设置。如果你想让你的项目加载一个特定的环境,那么你应该为编译器指定你想要加载的环境设置。

希望对您有所帮助。 祝你好运。

您需要在 visual studio 2017c 中找到您的解决方案点击解决方案,在菜单中点击属性 > 构建,您会看到已经为名为 Development 的环境创建了环境变量。如果您在给定 Web 项目的属性页中覆盖该值,它将从应用程序环境特定的应用程序设置中提取环境变量。如果您的版本是 2.1 或更高版本,我也会保留您的虚拟主机生成器默认代码

尝试使用 CreateDefaultBuilder(),它应该会为您提供所需的配置设置(如 docs 中的示例所示)。请注意,如果您在 Linux 上 运行,则它区分大小写 - 如果文件名的大写 P 表示 Production,则环境变量的值也必须如此。此外,检查文件是否位于正确的目录中 - 在运行时打印 Directory.CurrentDirectory() 的值。这是他们应该在的地方。

如果这可行,但您实际上并不需要默认构建器,只需从 the source.

复制您需要的部分

发现我有一个自定义 DesignTimeDbContextFactory class 用于迁移:

public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext> {
        public ApplicationDbContext CreateDbContext(string[] args) {
            var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
            string connectionString = Config.GetConnectionString("AppDbContext");
            builder.UseMySql(connectionString);

            return new ApplicationDbContext(builder.Options);
        }
    }

由于配置的注入在这里似乎不起作用(当时我在使用默认 Startup class 时收到连接字符串错误),我写了一些自定义配置 class:

public class Config {
        static IConfigurationRoot config;
        static IConfigurationRoot AppConfig {
            get {
                if (config == null) {
                    config = new ConfigurationBuilder()
                             .SetBasePath(Directory.GetCurrentDirectory())
                             .AddJsonFile("appsettings.json")
                             .Build();
                }
                return config;
            }
        }
        public static string GetConnectionString(string name) {
            var connectionString = AppConfig.GetConnectionString(name);
            return connectionString;
        }
    }

所以问题是,ASP.NET Core 的默认 ConfigureAppConfiguration 没有用于一致性。相反,我的解决方案只加载 appsettings.json,因为在撰写本文时 class,没有使用特定于环境的配置。

我只需要像这样添加加载:

    static IConfigurationRoot AppConfig {
        get {
            if (config == null) {
                var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
                config = new ConfigurationBuilder()
                         .SetBasePath(Directory.GetCurrentDirectory())
                         .AddJsonFile("appsettings.json")
                         // https://github.com/aspnet/MetaPackages/blob/rel/2.0.0/src/Microsoft.AspNetCore/WebHost.cs
                         .AddJsonFile($"appsettings.{environmentName}.json", optional: true, reloadOnChange: true)
                         .Build();
            }
            return config;
        }
    }

如果有人在这里有更清晰的解决方案,让我在 EF 迁移中使用默认 ConfigureAppConfiguration 方法,我将不胜感激,因为使用此类默认内容而不是自定义方法时,它似乎更不容易出错。

根据文档,JSON 配置提供程序应在 ASP.NET Core 2.1 中自动加载两次(并且 ASP.NET Core 2.1) 使用 CreateDefaultBuilder 时(因此请将您的代码从单独的 ConfigurationBuilder 中移出)。

AddJsonFile is automatically called twice when you initialize a new WebHostBuilder with CreateDefaultBuilder. The method is called to load configuration from:

  • appsettings.json – This file is read first. The environment version of the file can override the values provided by the appsettings.json file.
  • appsettings.{Environment}.json – The environment version of the file is loaded based on the IHostingEnvironment.EnvironmentName.

他们的例子:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.SetBasePath(Directory.GetCurrentDirectory());
            config.AddJsonFile(
                "config.json", optional: true, reloadOnChange: true);
        })

(如果您想使用启动 (UI MVC) 项目中的连接字符串,为了在不同的迁移项目中添加迁移,您可能需要检查 。)

Environment variable Settings Image

根据环境变量设置,我们可以使用 appsettings.environment.json 文件作为配置文件

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