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>
If this is to be done for Azure, you need to also add a little bit of magic to the ccproj file that contains the AzureWorkerRole to be deployed:
Err, looks like the comment system ate the xml. Here it is in a pastebin: http://pastebin.ca/2328824 [ pastebin.ca ] / 2328824
Brad, so in the same project file that we just edited right? I’m doing this on azure right now.
I get “Error Namespace prefix ‘xdt’ is not defined” at the config files. Any advice?
(my type of project is Windows Service)
Reblogged this on Nathan Renico and commented:
Excellent post on how to transform App.config.
Very nice fix for what should be inherent to Visual Studio WinForm Apps. Thanks
Will this solution work for VS2012 and once click deployment? I’m using VS2012 and .Net 4.5.
This will work for VS2012. I have tested it. Thanks!
This will work for VS2012. I have tested it. Thanks!
This will work for 2013 as well, for those who may ask in the future. I have used this trick several times.
So helpful!! Thanks a lot.