如何在 .NET Core MVC 项目中转换 appsettings.json?

Posted

技术标签:

【中文标题】如何在 .NET Core MVC 项目中转换 appsettings.json?【英文标题】:How do I transform appsettings.json in a .NET Core MVC project? 【发布时间】:2017-03-28 15:39:45 【问题描述】:

我在我的项目中添加了额外的 json 配置文件

appsettings.DEV.json
appsettings.QA.json

并根据环境将它们加载到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, reloadOnChange: true);
    ...

而且我了解如何更改环境:在项目属性中修改ASPNETCORE_ENVIRONMENT 环境变量的值。但是,似乎无法根据配置指定不同的环境变量,下拉列表被标记为“N/A”并被禁用。

我看到的唯一选择是手动更改环境变量值,以更改使用的 appsettings。我确定有一种方法可以自动完成,否则您将如何使用 CI? (除了使用脚本来改变环境变量,必须有更简单的方法)。

这里的目标是为三个环境设置自动构建和持续集成:DEV、QA 和 PROD。 DEV 和 QA 在同一台机器上,所以设置手动指定环境的环境变量不是一个选项。

【问题讨论】:

通过配置文件下拉菜单添加一个新配置文件或在launchsettings.json中手动添加一个 @EricB 如何将配置文件与构建配置相关联?或者,如果不是构建配置,您如何指定构建/发布时使用的配置文件? (我的目标是为不同的环境设置自动构建和持续集成,因此手动更改环境或配置文件不是一种选择) 那么听起来你可以访问目标机器并手动设置环境变量,但它应该是一次性的。 @EricB 这发生在我身上,但是我们在同一台机器上托管了两个不同的环境(DEV 和 QA),而生产在它自己的机器上。因此,此解决方案不适用于 DEV|QA 我以前从未使用过该提供程序,您现在只能靠自己了:P 【参考方案1】:

根据构建类型确定 EnvironmentName

对于任何想根据构建类型设置 EnvironmentName 的人,有方便的 .UseEnvironment(environmentName) on WebHostBuilder(在 Program Main 中找到)。

只要针对项目中的构建配置设置了适当的编译符号,您就可以执行以下操作来确定 EnvironmentName:

public static void Main(string[] args)

    string environmentName;
#if DEBUG
    environmentName = "Development";
#elif STAGING
    environmentName = "Staging";
#elif RELEASE
    environmentName = "Production";
#endif

    var host = new WebHostBuilder()
        .UseKestrel()
        .UseEnvironment(environmentName)
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseStartup<Startup>()
        .UseApplicationInsights()
        .Build();

    host.Run();

【讨论】:

什么是#if DEBUG @Toolkit #if 是预处理器指令:docs.microsoft.com/en-us/dotnet/csharp/language-reference/…。 DEBUG 是一个预定义的预处理器符号,当您在项目中选中“定义调试常量”时设置它。【参考方案2】:

如果您使用Program.cs 中的默认代码,则除了在项目中创建两个文件之外,您无需执行任何操作。

Program.cs 中的默认代码如下所示:

public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .Build();

Here's what that's actually doing:

public static IWebHostBuilder CreateDefaultBuilder(string[] args)

    var builder = new WebHostBuilder();

    ...

    builder.ConfigureAppConfiguration((hostingContext, config) =>
    
        var env = hostingContext.HostingEnvironment;

        config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
              .AddJsonFile($"appsettings.env.EnvironmentName.json", optional: true, reloadOnChange: true);
    );

    ...

    return builder;

env.EnvironmentName 设置为ASPNETCORE_ENVIRONMENT 环境变量的值,因此您只需创建appsettings.ASPNETCORE_ENVIRONMENT.json 文件,它将自动合并。

附加说明:要让两个文件真正合并,请使用以下语法:

var appSettings = Configuration.GetSection("AppSettings").Get<AppSettings>();

不是:

var appSettings = new AppSettings();
Configuration.Bind("AppSettings", appSettings);
return appSettings;

后者不会返回合并后的数据。

感谢 Shawn Wildermuth 提供this。

【讨论】:

当然,你需要在目的机器上添加环境变量,不过我想这是不言而喻的。 没错,但我通常只在我的开发或测试机器上使用这个技巧来让它使用我的开发或测试设置。我不想依赖生产机器上的环境变量。 您愿意解释一下原因吗?我只是好奇? 在我看来,环境变量就是这样 - 一个变量,它有太多可能会被改变,或者无法发布等等。这对我来说似乎有点可怕产品环境。但这只是我个人的喜好。【参考方案3】:

我从 Tsengs 的回答中找到了一个解决方案,但为了清楚起见,我想在这里描述一下。 解决方案在另一个问题的答案中找到,但是问题完全不同(我也扩展了答案)所以我不认为这个问题应该被标记为重复。

答案是here

解决方案是在每个 IIS 站点上为密钥 ASPNETCORE_ENVIRONMENT 设置不同的环境变量值

这样做的步骤是:

    在 IIS 中转到您的应用程序并选择 Configuration Editor。 选择Configuration EditorSection 组合框中选择system.webServer/aspNetCore(RC2 和 RTM)或system.webServer/httpPlatform (RC1) 在From 组合框中选择Applicationhost.config ...。 点击enviromentVariables元素并打开编辑窗口。 设置您的环境变量。 关闭窗口并单击应用。 完成

或者,您可以修改您的applicationHost.config 文件(通常位于C:\Windows\System32\inetsrv\config\applicationHost.config

并在根 &lt;Configuration&gt; 标记下添加以下条目,其中“my-iis-site”是您的 IIS 站点的名称。

<location path="my-iis-site">
    <system.webServer>
        <aspNetCore>
            <environmentVariables>
                <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="DEV" />
            </environmentVariables>
        </aspNetCore>
    </system.webServer>
</location>

【讨论】:

【参考方案4】:

您在图片中链接的对话框仅用于配置“launchSettings.json”。此文件您的应用程序未使用此文件

它仅用于 Visual Studio 设置环境并在您按 F5 和 nothing 时在浏览器中打开 URL。

当你想切换环境时,你需要在启动前设置一个环境变量。如何做到这一点,取决于您的环境。

Windows(命令行、cmd.exe)

setx ASPNETCORE_ENVIRONMENT "Development"

Windows (Powershell)

$Env:ASPNETCORE_ENVIRONMENT = "Development"

Linux

export ASPNETCORE_ENVIRONMENT="Development"

Linux(设置为单个命令)

ASPNETCORE_ENVIRONMENT="Development" dotnet run

关于评论的更新

是的,它是特定于机器的(Linux 除外,您可以按命令执行)。但是,在 IIS 中,您也可以通过不同的应用程序池或按照 this answers 说明将其添加到 IIS 中来实现

【讨论】:

当您说“启动前设置环境变量”时,您是指某种启动脚本吗?而且这个变量当然是特定于机器的,那么这将如何解决我在同一物理机器上托管两个环境的问题,在两个不同的 IIS 站点中? 嗯,它被称为“环境”是有原因的。是的,它是特定于机器的(Linux 除外,您可以按命令执行)。但是,在 IIS 中,您也可以这样做 iirc,但您需要不同的应用程序池,但我相信它涉及将配置文件分配给应用程序池并在该用户配置文件中设置环境变量 或者查看这个答案***.com/a/36836533/455493。无论如何,您的管理员应该知道如何做到这一点,这是他们的工作;) 如果我们无法访问 Web 服务器上的环境变量怎么办?【参考方案5】:

如果您使用的是 azure,请将具有相应值的 ASPNETCORE_ENVIRONMENT 添加到 webapp 一侧的应用程序设置中,然后它将获取正确的 appsettings.value.json 文件

【讨论】:

我们为什么要这样做?那么它就不再是配置值,而是必须作为代码签入。

以上是关于如何在 .NET Core MVC 项目中转换 appsettings.json?的主要内容,如果未能解决你的问题,请参考以下文章

如何将项目引用添加到 ASP.NET Core 1.0 MVC 项目

从 ASP.NET MVC 迁移到 ASP.NET Core MVC

如何在 .net Core MVC 控制器中返回 HttpResponseMessage 而不将其序列化为 JSON?

ASP.NET Core MVC 项目无法加载程序集

如何在 ASP.NET Core 5 MVC (.NET 5) 中获取记录的用户数据?

asp.net core mvc权限控制:分配权限