Enable app.debug.config app.release.config

For now only web.config supports transformation (web projects).
This transformations allow you can have different settings for different configurations (debug or release). A good example is transformation of a connection string. Probably you will have a different connection string when you release the app in production.

Doing the following steps you can obtain transformation on a app.config too.

1. Prepare your project and add app.config, app.debug.config and app.release.config. Make sure is running under .Net 4.0 .

2. Right click on the project, click Unload project and then Edit .csproj.

3. Below the last PropertyGroup add the following:

  <PropertyGroup>
    <ProjectConfigFileName>App.config</ProjectConfigFileName>
  </PropertyGroup>

4. Modify the section ItemGroup that’s related to app.config/app.*.config files

 <ItemGroup>
    <None Include="App.config" />
    <None Include="App.Debug.config">
      <DependentUpon>App.config</DependentUpon>
    </None>
    <None Include="App.Release.config">
      <DependentUpon>App.config</DependentUpon>
    </None>
  </ItemGroup>

5.Below the last Import tag insert this one

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets" />

6.Right before end of Project tag add this

  <Target Name="AfterBuild">
    <TransformXml Source="@(AppConfigWithTargetPath)" Transform="$(ProjectConfigTransformFileName)" Destination="@(AppConfigWithTargetPath->'$(OutDir)%(TargetPath)')" />
  </Target>

7.Now you can save the project, right click the project and choose Reload Project.

8.For app.debug.config / app.release.config files you can use the template that’s provided for web projects, which looks like this below:

<?xml version="1.0"?>

<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">

  <appSettings>
    <add key="Mode" value="Debug" xdt:Transform="Insert"/>
  </appSettings>
  <!--
    In the example below, the "SetAttributes" transform will change the value of 
    "connectionString" to use "ReleaseSQLServer" only when the "Match" locator 
    finds an atrribute "name" that has a value of "MyDB".
    
    <connectionStrings>
      <add name="MyDB" 
        connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" 
        xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
    </connectionStrings>
  -->
  <system.web>
    <!--
      In the example below, the "Replace" transform will replace the entire 
      <customErrors> section of your web.config file.
      Note that because there is only one customErrors section under the 
      <system.web> node, there is no need to use the "xdt:Locator" attribute.
      
      <customErrors defaultRedirect="GenericError.htm"
        mode="RemoteOnly" xdt:Transform="Replace">
        <error statusCode="500" redirect="InternalError.htm"/>
      </customErrors>
    -->
  </system.web>
</configuration>

Full example of .csproj is here:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
    <ProductVersion>8.0.30703</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{BDB79931-AFF6-417E-9DC2-773671C69BF7}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>AppConfigDebug</RootNamespace>
    <AssemblyName>AppConfigDebug</AssemblyName>
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <TargetFrameworkProfile>
    </TargetFrameworkProfile>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <PlatformTarget>x86</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <PlatformTarget>x86</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup>
    <ProjectConfigFileName>App.config</ProjectConfigFileName>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="App.config" />
    <None Include="App.Debug.config">
      <DependentUpon>App.config</DependentUpon>
    </None>
    <None Include="App.Release.config">
      <DependentUpon>App.config</DependentUpon>
    </None>
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
  <Target Name="AfterBuild">
    <TransformXml Source="@(AppConfigWithTargetPath)" Transform="$(ProjectConfigTransformFileName)" Destination="@(AppConfigWithTargetPath->'$(OutDir)%(TargetPath)')" />
  </Target>
</Project>

32 Comments

  1. Very usefull. Thanks. Btw, in the 5th point you can use inderect version shotcut – $(VisualStudioVersion)
    For example,

    It’s more convinient in cases when you don’t know exact version of a build agent.

    Reply

  2. It works great. On VisualStudio 2015 you have to do step 5 and 6 also.
    And use different number for visual studio version:

    Reply

    1. Import Project=”$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.targets”

      Reply

    1. Works like a charm.
      I just had forgot to add:

      App.config

      So transformation source path was default to Web.debug.config… Also VS version has to be changed accordingly.

      Thank you for the tip!

      Reply

    1. Hope the markup filter won’t trip me up again …

      Project=”$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.targets”

      Reply

  3. Great Information! One question though when you publish this is there a way to point to specific configuration in visual studio 2017

    Reply

  4. but when publishing it, there always used the content of App.config, do not replace with App.Release.config, Is that something i don’t understand? please kindly advice. thanks.

    Reply

  5. Pouah !! And I read everywhere that Visual Studio is more “productive” ! This way is just dirty ! It’s easier in Java, I still don’t understand why people like .NEt !
    And yes, I’m angry because I must take care of a .Net project and this kind of “best practice” is just a bullshit to do on Visual
    #MavenProfile !

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s