如何使用MSBuild编写一个执行appSettings.json转换的任务?

3

我有一个ASP .NET Core应用程序,我想将其部署到两个不同的环境中:1)Staging,2)Production。我的项目中有以下文件,这些文件包含数据库connectionStrings:

appSettings.json
appSettings.staging.json
appSettings.production.json

假设connectionString的名称为"MyDb",我希望在生产环境下使用appSettings.production.json中的值来替换appSettings.json中"MyDb"的值,在staging环境下使用appSettings.staging.json中的值。如何实现呢?以下是详细步骤示例:
1个回答

4
如何编写一个任务,使用MSBuild执行appSettings.json的转换?
您可以在项目文件中添加自定义任务ReplaceFileText
为了实现这个目标,您需要卸载您的项目。然后在项目的最后,在结束标签</Project>之前,放置以下脚本:
<UsingTask TaskName="ReplaceFileText" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
      <InputFilename ParameterType="System.String" Required="true" />
      <OutputFilename ParameterType="System.String" Required="true" />
      <MatchExpression ParameterType="System.String" Required="true" />
      <ReplacementText ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Reference Include="System.Core" />
      <Using Namespace="System" />
      <Using Namespace="System.IO" />
      <Using Namespace="System.Text.RegularExpressions" />
      <Code Type="Fragment" Language="cs">
        <![CDATA[
            File.WriteAllText(
                OutputFilename,
                Regex.Replace(File.ReadAllText(InputFilename), MatchExpression, ReplacementText)
                );
          ]]>
      </Code>
    </Task>
  </UsingTask>

  <Target Name="TransformsWithProduction" Condition="'$(Configuration)'=='Production'" AfterTargets="Build"> 
    <ReplaceFileText
      InputFilename="$(ProjectDir)appsettings.json"
      OutputFilename="$(ProjectDir)appsettings.json"
      MatchExpression="MyDb"
      ReplacementText="MyDbProduction" />
  </Target>

  <Target Name="TransformsWithProduction" Condition="'$(Configuration)'=='staging'" AfterTargets="Build">
    <ReplaceFileText
      InputFilename="$(ProjectDir)appsettings.json"
      OutputFilename="$(ProjectDir)appsettings.json"
      MatchExpression="MyDb"
      ReplacementText="MyDbstaging" />
  </Target>

上述示例将“MyDb”替换为“MyDbstaging”或“MyDbProduction”在文件appSettings.json中。

此外,为了能够重复使用此任务,而无需在每次修改后手动恢复appSettings.json文件中的值为“MyDb”,我们可以添加另一个任务来恢复这个值:

  <Target Name="RestoreJsonFile" BeforeTargets="Build">
    <Copy
            SourceFiles="$(ProjectDir)\BackupJsonFile\appsettings.json"
            DestinationFolder="$(ProjectDir)"
        />
  </Target>

appSettings.json文件备份到BackupJsonFile文件夹中,然后将其替换为已修改的文件。

因此,最终的自定义任务应该是:

 <UsingTask TaskName="ReplaceFileText" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
      <InputFilename ParameterType="System.String" Required="true" />
      <OutputFilename ParameterType="System.String" Required="true" />
      <MatchExpression ParameterType="System.String" Required="true" />
      <ReplacementText ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Reference Include="System.Core" />
      <Using Namespace="System" />
      <Using Namespace="System.IO" />
      <Using Namespace="System.Text.RegularExpressions" />
      <Code Type="Fragment" Language="cs">
        <![CDATA[
            File.WriteAllText(
                OutputFilename,
                Regex.Replace(File.ReadAllText(InputFilename), MatchExpression, ReplacementText)
                );
          ]]>
      </Code>
    </Task>
  </UsingTask>

  <Target Name="RestoreJsonFile" BeforeTargets="Build">
    <Copy
            SourceFiles="$(ProjectDir)\BackupJsonFile\appsettings.json"
            DestinationFolder="$(ProjectDir)"
        />
  </Target>

  <Target Name="TransformsWithProduction" Condition="'$(Configuration)'=='Production'" AfterTargets="RestoreJsonFile"> 
    <ReplaceFileText
      InputFilename="$(ProjectDir)appsettings.json"
      OutputFilename="$(ProjectDir)appsettings.json"
      MatchExpression="MyDb"
      ReplacementText="MyDbProduction" />
  </Target>

  <Target Name="TransformsWithstaging" Condition="'$(Configuration)'=='staging'" AfterTargets="RestoreJsonFile">
    <ReplaceFileText
      InputFilename="$(ProjectDir)appsettings.json"
      OutputFilename="$(ProjectDir)appsettings.json"
      MatchExpression="MyDb"
      ReplacementText="MyDbstaging" />
  </Target>

enter image description here

顺便提一下,如果要替换appSettings.json中的MyDb值不是您唯一的选择,您可以尝试在构建运行生产环境时使用appSettings.production.json而不是替换appSettings.json中的值。有关详细信息,请参见ASP.NET Core中的配置转换ASP.Net Core Web API中的Appsettings.json配置

希望这可以帮助到您。


在按照上述步骤操作后,我将活动解决方案配置更改为“生产”,并构建了项目,但是在appSettings.json文件中没有看到任何更改。 - Farooq Hanif
@Dev_Net,这是我的错。我在“TransformsWithProduction”中重复复制了目标名称,现在我已经更新了它,你可以检查一下,我已经在我的端上测试过了,它运行得很好。 - Leo Liu
谢谢,Leo,这没有出现任何问题。有几件事情:1)我如何将appSettings.json中名为“connectionStrings”的整个部分替换为appSettings.Production.json或appSettings.Staging.json中的相同部分?2)是否可能仅在需要发布代码时运行这些构建任务,而不是在每次构建时运行? - Farooq Hanif
@Dev_Net,对于问题1),是的,你可以这样做。只需要用&quot;替换双引号即可。对于第二个问题,恐怕不行。因为条件是'$(Configuration)'=='Production',这个值无法传递到发布过程中,只能由构建过程支持。 - Leo Liu
感谢您的帮助 :) - Farooq Hanif
如何在构建任务中使用NewtonSoft.Json? - Farooq Hanif

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