Inspired by Oleg and others in this question, I took the solution https://stackoverflow.com/a/5109530/2286801 a step further to enable the following.
This solution works by performing the app.config transformation before the app.config is referenced for the first time in the MSBuild process. It uses an external targets file for easier management across multiple projects.
Similar steps to the other solution. I've quoted what remains the same and included it for completeness and easier comparison.
0. Add a new file to your project called AppConfigTransformation.targets
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Transform the app config per project configuration.-->
<PropertyGroup>
<!-- This ensures compatibility across multiple versions of Visual Studio when using a solution file.
However, when using MSBuild directly you may need to override this property to 11.0 or 12.0
accordingly as part of the MSBuild script, ie /p:VisualStudioVersion=11.0;
See http://blogs.msdn.com/b/webdev/archive/2012/08/22/visual-studio-project-compatability-and-visualstudioversion.aspx -->
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.targets" />
<Target Name="SetTransformAppConfigDestination" BeforeTargets="PrepareForBuild"
Condition="exists('app.$(Configuration).config')">
<PropertyGroup>
<!-- Force build process to use the transformed configuration file from now on. -->
<AppConfig>$(IntermediateOutputPath)$(TargetFileName).config</AppConfig>
</PropertyGroup>
<Message Text="AppConfig transformation destination: = $(AppConfig)" />
</Target>
<!-- Transform the app.config after the prepare for build completes. -->
<Target Name="TransformAppConfig" AfterTargets="PrepareForBuild" Condition="exists('app.$(Configuration).config')">
<!-- Generate transformed app config in the intermediate directory -->
<TransformXml Source="app.config" Destination="$(AppConfig)" Transform="app.$(Configuration).config" />
</Target>
</Project>
1. Add an XML file for each configuration to the project.
Typically you will have Debug and Release configurations so name your files App.Debug.config and App.Release.config. In my project, I created a configuration for each kind of enironment so you might want to experiment with that.
2. Unload project and open .csproj file for editing
Visual Studio allows you to edit .csproj right in the editor—you just need to unload the project first. Then right-click on it and select Edit .csproj.
3. Bind App.*.config files to main App.config
Find the project file section that contains all App.config and App.*.config references and replace as follows. You'll notice we use None instead of Content.
<ItemGroup>
<None Include="app.config"/>
<None Include="app.Production.config">
<DependentUpon>app.config</DependentUpon>
</None>
<None Include="app.QA.config">
<DependentUpon>app.config</DependentUpon>
</None>
<None Include="app.Development.config">
<DependentUpon>app.config</DependentUpon>
</None>
</ItemGroup>
4. Activate transformations magic
In the end of file after
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
and before final
</Project>
insert the following XML:
<Import Project="AppConfigTransformation.targets" />
Done!