Transform app.config for 3 different environment

App.config transforms

To test if transforms work you have to use real transforms. Insert-transform with appSettings block is maybe simplest one. I tested with following configuration files.

App.config:

<?xml version="1.0" encoding="utf-8" ?><configuration>  <appSettings>    <add key="FirstName" value="Gunnar"/>  </appSettings></configuration>

App.Release.config

<?xml version="1.0"?><configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">  <appSettings>    <add key="LastName" value="Peipman" xdt:Transform="Insert"/>  </appSettings></configuration>

Configuration file after transform:

<?xml version="1.0" encoding="utf-8" ?><configuration>  <appSettings>    <add key="FirstName" value="Gunnar"/>    <add key="LastName" value="Peipman"/>  </appSettings></configuration>

Making App.config transforms work

Let’s see how to do it with console application.

  1. Add App.config and App.Release.config to your project and fill them with content given above..
  2. Unload console application project.
  3. Right-click on project name and select "Edit <project file name>".
  4. Project file is opened as XML-file and you can see what is inside it.
  5. Before closing tag of first property group add the following line:

    <ProjectConfigFileName>App.Config</ProjectConfigFileName>
    
  6. Find <ItemGroup> where App.Config is defined (<None Include="App.Config" />) and add the following block after App.Config node:

    <None Include="App.Release.config"> 
        <DependentUpon>App.Config</DependentUpon>
    </None>
    
  7. Find first <Import Project= node and add the following import as last one to list:

    <Import Project="$(VSToolsPath)\Web\Microsoft.Web.Publishing.targets" Condition="'$(VSToolsPath)' != ''" />
    <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets" Condition="false" />
    
  8. To the end of file, just before tag, paste the following block of code:

    <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
    <Target Name="AfterCompile" Condition="exists('app.$(Configuration).config')">
      <TransformXml Source="app.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="app.$(Configuration).config" />
      <ItemGroup>
        <AppConfigWithTargetPath Remove="app.config" />
        <AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
          <TargetPath>$(TargetFileName).config</TargetPath>
        </AppConfigWithTargetPath>
        <AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
          <TargetPath>$(TargetName).vshost$(TargetExt).config</TargetPath>
        </AppConfigWithTargetPath>
      </ItemGroup>
    </Target>
    
  9. Save project file, close it and reload it.

When loading project again Visual Studio may ask you about some modifications to file so all versions from Visual Studio 2010 to current are able to use your project file with no modifications to it. Agree with it because then you don’t have dependencies to Visual Studio versions.


I think what is confusing is that we have the ability to make compile-time config transformations and then we have deployment-time config transformations.

In general, you use compile-time config transformations to make changes to your locally-defaulted config file so that it is appropriate for a DEBUG or RELEASE configuration (or any custom configuration you define). For web.config, the tooling is built-in. For app.config, the SlowCheetah Visual Studio extension brings the same capability that we have for web.config to app.config. An example of a config transform for a RELEASE configuration is to remove the debug attribute on system.web compilation.

Deployment-time config transformations are manipulations of the config file while deploying to a specific environment (e.g. QA, PROD). Database connection strings need to change, service endpoints change, etc... For web.config, MSDEPLOY is the IIS tool of choice. For app.config, it seems we need to rely on installer technology. There are different tools for this, like WIX for example.

Anyway, I hope this short explanation of the distinction between compile-time and deployment-time config transformations helps explain why the toolset is fragmented. For more in-depth analysis, you can refer to a blog post I made on this subject: http://philippetruche.wordpress.com/2012/07/11/deploying-web-applications-to-multiple-environments-using-microsoft-web-deploy/

If choosing to use the WIX toolset to produce installers, refer to Creating Multi-Environment Windows Installers with Visual Studio 2012 and Wix.