Config transforms in dotnet core iis apps

I’ve done my first .net core app and been happily coding and deploying up the environment chain. Each deployment I was cursing myself, saying “oh that’s right … don’t forget to change the config settings. I need to include that in the build. Next time…”

My setup was a little different as in I had to target the full dotnet framework instead of standard. As a result I had config files everywhere. The normal appsettings.json file and its subsets, appsettings.Test.json and appsettings.Production.json. A web.config and an app.config.

All I want to do at the end of a development sprint is to deploy it to Test or Prod with as little effort as possible.

Bring back XML Transforms…

Using Nuget, add DotNet.xdt to the web project. (Following the instructions on https://github.com/nil4/dotnet-transform-xdt)

Edit the project file as follows.

  <ItemGroup>
    <!-- other DotNetCliToolReference's -->
    <DotNetCliToolReference Include="Microsoft.DotNet.Xdt.Tools" Version="2.0.0" />
  </ItemGroup>

To do a xml transform on the web config insert this at the end of the project file.

<!--Ref: https://github.com/nil4/dotnet-transform-xdt-->
  <Target Name="ApplyXdtConfigTransform" BeforeTargets="_TransformWebConfig">
    <PropertyGroup>
      <_SourceWebConfig>$(MSBuildThisFileDirectory)web.config</_SourceWebConfig>
      <_XdtTransform>$(MSBuildThisFileDirectory)web.$(Configuration).config</_XdtTransform>
      <_TargetWebConfig>$(PublishDir)web.config</_TargetWebConfig>
    </PropertyGroup>
    <Exec Command="dotnet transform-xdt --xml &quot;$(_SourceWebConfig)&quot; --transform &quot;$(_XdtTransform)&quot; --output &quot;$(_TargetWebConfig)&quot;" Condition="Exists('$(_XdtTransform)')" />
  </Target>

</Project>

And another one for the app config. This one is slightly different because it uses the publish directory which already has the projname.exe.config file created.

<Target Name="ApplyXdtConfigTransform2" BeforeTargets="_TransformWebConfig">
    <PropertyGroup>
      <_SourceAppConfig>$(PublishDir)$(TargetFileName).config</_SourceAppConfig>
      <_XdtAppConfigTransform>$(MSBuildThisFileDirectory)app.$(Configuration).config</_XdtAppConfigTransform>
      <_TargetAppConfig>$(PublishDir)$(TargetFileName).config</_TargetAppConfig>
    </PropertyGroup>
    <Exec Command="dotnet transform-xdt --xml &quot;$(_SourceAppConfig)&quot; --transform &quot;$(_XdtAppConfigTransform)&quot; --output &quot;$(_TargetAppConfig)&quot;" Condition="Exists('$(_XdtAppConfigTransform)')" />
  </Target>

</Project>

Create the config transform files.

Config_transforms_in_dotnet_core_iis_apps1

D__Work_Blog_Config_transforms_in_dotnet_core_iis_apps_Config_transforms_in_dotnet_core_iis_apps2

app.Test.config sample content.

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings>
    <add name="KapuniAlarms.ReportLibrary.Properties.Settings.KapuniAlarmsReportsLibrary"
        connectionString="Data Source=CT-DBA-SQL008;Initial Catalog=KapuniAlarms;Integrated Security=True"
        providerName="System.Data.SqlClient"
          xdt:Transform="SetAttributes(connectionString)" xdt:Locator="Match(name)" />
  </connectionStrings>
</configuration>

web.Test.config

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.webServer>
    <aspNetCore processPath="%LAUNCHER_PATH%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="true" arguments="%LAUNCHER_ARGS%"
                 xdt:Transform="SetAttributes(stdoutLogEnabled)" >
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Test" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"  />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</configuration>

Create your Publish Profile and configuration names to match, and deploy away.

Config_transforms_in_dotnet_core_iis_apps3