如何在.Net核心应用程序中发布特定于环境的应用程序?

LP1*_*P13 31 .net-core coreclr asp.net-core asp.net-core-1.0

appsettings我的.Net核心应用程序中有3个特定于环境的文件

在此输入图像描述

project.json我这样设置publishOptions.(根据此处的建议)

"publishOptions": {
    "include": [
      "wwwroot",      
      "appsettings.development.json",
      "appsettings.staging.json",
      "appsettings.production.json",
      "web.config"
    ]
  },
Run Code Online (Sandbox Code Playgroud)

我有3个相应的启动类,它们使用适当appsettings的环境

var builder = new ConfigurationBuilder()
    .SetBasePath(env.ContentRootPath)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: false, reloadOnChange: true);
Run Code Online (Sandbox Code Playgroud)

但是,当我发布应用程序时,所有3个appsettings文件都会在所有环境中结束.如何发布特定于环境的appsetting文件?

Sen*_*hoh 16

我最近也不得不为此找到一个解决方案,我通过向.csproj文件添加一些设置并对Program.cs.

<Project Sdk="Microsoft.NET.Sdk.Web">
    <!-- ... -->
    <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
        <DebugSymbols>true</DebugSymbols>
        <DebugType>full</DebugType>
        <DefineConstants>DEBUG;TRACE</DefineConstants>
        <EnvironmentName>Development</EnvironmentName>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
        <DebugType>pdbonly</DebugType>
        <Optimize>true</Optimize>
        <EnvironmentName>Production</EnvironmentName>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Stage|AnyCPU'">
        <DebugType>pdbonly</DebugType>
        <Optimize>true</Optimize>
        <EnvironmentName>Staging</EnvironmentName>
    </PropertyGroup>
    <ItemGroup>
        <Content Remove="appsettings.json" />
        <Content Remove="appsettings.*.json" />
    </ItemGroup>
    <ItemGroup>
        <Content Include="appsettings.json" CopyToOutputDirectory="PreserveNewest" />
        <Content Include="appsettings.*.json" Exclude="appsettings.$(EnvironmentName).json" DependentUpon="appsettings.json" CopyToOutputDirectory="Never" />
        <Content Include="appsettings.$(EnvironmentName).json" DependentUpon="appsettings.json" CopyToOutputDirectory="PreserveNewest" />
    </ItemGroup>

    <Target Name="RenameAppsettings" AfterTargets="Publish">
        <Move SourceFiles="$(PublishDir)\appsettings.$(EnvironmentName).json" DestinationFiles="$(PublishDir)\appsettings.overrides.json" />
    </Target>
</Project>
Run Code Online (Sandbox Code Playgroud)

为了稍微解释一下,我<EnvironmentName>为每个配置添加了一个元素,以便在构建过程中使用它。我使用appsettings.{EnvironmentName}.json(即appsettings.Staging.json)作为一个“覆盖”文件,所以我只是让它在构建过程中重命名必要的 JSON 文件。dotnet publish -c Stage例如,当您运行 时,它会将appsettings.Staging.json文件发布到发布文件夹并将其重命名为appsettings.overrides.json. 在您的 中Program.cs,您只需要包含该appsettings.overrides.json文件:

    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
    .AddJsonFile($"appsettings.overrides.json", optional: true, reloadOnChange: true)
Run Code Online (Sandbox Code Playgroud)

我希望它有帮助!

旁注:我包含appsettings.*.json并将其设置为CopyToOutputDirectory="Never"只是这样它们在开发时仍然显示在 Visual Studio 中。否则,如果您只想appsettings在 VS 中显示当前环境的文件,只需从csproj文件中删除该行。


She*_*R A 13

简单的解决方案是在发布配置文件 (.pubxml) 中指定环境名称。这样您就不需要将其添加到环境变量中,并且可以在同一服务器上托管具有多种配置的应用程序。

<EnvironmentName>{Enviornment name}</EnvironmentName>
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

应用程序发布后将使用相应的appsettings.json文件。发布后您可以看到所有 .json 文件,但应用程序将仅使用环境设置值。

  • 尝试了这个,在发布时我刚刚复制了所有 3 个 `appsettings.*.json` 文件,我预计只会复制 1 个 (3认同)

Gab*_*abo 8

您可以使用 MSBuild 条件选择性地将文件包含在编译输出(或发布的输出)中。

<ItemGroup Condition="'$(Configuration)'=='Release'">
  <Content Remove="appsettings.Development.json;appsettings.Staging.json" />
  <None Include="appsettings.Development.json;appsettings.Staging.json" />
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)

当编译目标配置为 Release 时,以上内容会忽略 Development 和 Staging appsettings.json 文件变体。


小智 5

如果其他人想知道如何在多个环境中使用不同的应用程序设置,这里是一个可能的解决方案。

dotnet publish --configuration [Debug|Release]如果*.csproj这些文件具有条件逻辑,将把相应的appsettings.json文件复制到publish文件夹中:

  • 首先,在.pubxml发布配置文件(可以在Visual Studio的Properties-> PublishProfiles中找到)中,禁用默认情况下包含所有内容文件
<PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <EnableDefaultContentItems>false</EnableDefaultContentItems>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)
  • 然后指定条件调试/发布逻辑
<Choose>
    <When Condition="'$(Configuration)' == 'Debug'">
      <ItemGroup>
        <None Include="appsettings.json" CopyToOutputDirectory="Always" CopyToPublishDirectory="Always" />
        <None Include="appsettings.prod.json" CopyToOutputDirectory="Never" CopyToPublishDirectory="Never" />
      </ItemGroup>
    </When>
    <When Condition="'$(Configuration)' == 'Release'">
      <ItemGroup>
        <None Include="appsettings.json" CopyToOutputDirectory="Never" CopyToPublishDirectory="Never" />
        <None Include="appsettings.prod.json" CopyToOutputDirectory="Always" CopyToPublishDirectory="Always" />
      </ItemGroup>
    </When>
</Choose>
Run Code Online (Sandbox Code Playgroud)
  • 最后在里面Startup.cs尝试加载两个文件
public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile($"appsettings.prod.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.json", optional: true, reloadOnChange: true)
        .AddEnvironmentVariables();

    Configuration = builder.Build();
}
Run Code Online (Sandbox Code Playgroud)

希望此解决方案对您有所帮助。

  • 不按要求回答问题。 (4认同)
  • 我认为它确实按照要求回答。每个环境在发布时仅获取相关的 appsettings 文件。 (4认同)
  • @Ben,这个答案实际上必须标记为答案!它对我来说就像一个魅力! (2认同)
  • “很高兴知道”方法,但没有回答问题,因为它清楚地说明了针对不同环境(如登台、生产、开发等)的发布,但这个答案尝试使用“配置”来解决问题。 (2认同)

Tse*_*eng 1

一种可能的方法是运行预发布或发布后脚本/命令,例如通过运行 gulp 任务执行(或者使用部分dotnet publish-iis中的任务将文件复制到发布前)。prepublishscripts

将其添加到您的project.json:

"scripts": {
  "postpublish": [ "gulp cleanconfig", "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
Run Code Online (Sandbox Code Playgroud)

您还可以在此处运行 cmd 或 shell 命令。但实际上,您首先不应该这样做,只需发送所有 3 个 appconfig 文件,因为在 Azure 应用服务上,您可以根据通过以下方式调节的环境变量来切换模式: Azure Portal 和发布时,暂存槽和生产槽将仅交换,但环境变量保留。

不过,您不应该在 appsettings.json 中存储机密(我假设您这样做以及您想要删除文件的原因)。相反,使用“用户机密”进行开发,使用环境变量来设置连接字符串等以进行生产。工作起来很有魅力,尤其是与 Azure 应用服务和 Docker 容器一起使用。

  • 我在应用程序设置中没有任何秘密。但是,我们在应用程序设置中确实有连接字符串,每个环境的连接字符串都不同。我认为在应用程序设置中包含连接字符串是完全可以的。我真的不明白为什么我必须克服重重困难才能发布特定于环境的应用程序设置。事实上,这应该是发布过程的标准行为。我认为没有人希望所有应用程序设置文件最终出现在所有环境中..我认为我们在这里遗漏了一些东西.. (5认同)
  • 最后我最终使用 Powershell 脚本来复制文件。在脚本中,我有根据环境复制应用程序设置文件的逻辑。 (3认同)
  • 好吧,如果连接字符串中有用户名和密码或 api 密钥,那么它就是一个秘密。如果没有,发布所有 3 个文件也没什么坏处。到底是什么事情呢? (2认同)
  • 它没有用户名/密码。此外,它与 appsetting 文件实际包含哪些数据的问题无关 (2认同)