I have a ASP .NET Core application that I want to deploy to 2 different environments: 1) Staging, 2) Production. I have the following files in my project that contains database connectionStrings:
appSettings.json
appSettings.staging.json
appSettings.production.json
lets say, the name of connectionString is "MyDb". I want the ability to replace the value of MyDb in appSettings.json with one in appSettings.production.json if the build is run for Production and with appSettings.staging.json if the build is run for staging.
How can I do that? A step by step example would be great.
how to write a task that performs appSettings.json transforms using MSBuild?
You can add a custom task ReplaceFileText into the project file.
To accomplish this, unload your project. Then at the very end of the project, just before the end-tag </Project>, place below scripts:
<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>
The above example replaces "MyDb" with "MyDbstaging" or "MyDbProduction" in the file appSettings.json.
Besides, in order to be able to re-use this task without the need to manually restore the value to "MyDb" in the appSettings.json file after each modification, we could add a another task to restore this value:
<Target Name="RestoreJsonFile" BeforeTargets="Build">
<Copy
SourceFiles="$(ProjectDir)\BackupJsonFile\appsettings.json"
DestinationFolder="$(ProjectDir)"
/>
</Target>
Back up that appSettings.json in the back up folder BackupJsonFile, then copy it to replace the one that has been modified.
So the final custom task should be:
<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>

BTW, if replace the value of MyDb in appSettings.json is not your only option, you can try to use appSettings.production.json if the build is run for Production instead of replacing the value in appSettings.json. See Config transformations in ASP.NET Core and Appsettings.json configuration in ASP.Net Core Web API more detailed info.
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With