web.config transformation does not work on build server

17,438

Solution 1

We've been using publish targets in our web application projects and had seen that the build process was correctly transforming our web.config files, but when we moved the build to our CI server, the transforms were not being applied.

The MSBuild script were using was:

MSBuild.exe PATH_TO_PROJ.csproj /p:DeployOnBuild=true /p:PublishProfile=PUBLISH_TARGET

What we found was that we still needed to specify the Configuration as Debug or Release (even though this appears to be an attribute of the publish target.)

MSBuild.exe PATH_TO_PROJ.csproj /p:DeployOnBuild=true /p:PublishProfile=PUBLISH_TARGET /p:Configuration=Release

Solution 2

I believe that for config transforms to occur when publishing using MSBuild rather than Visual Studio, you need to add a TransformXml task to your project.

This answer gives a guide on what you need to add, but to save a click:

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<Target Name="BeforeBuild">
    <TransformXml Source="Web.config" Transform="Web.$(Configuration).config" Destination="Web.config" />
</Target>

You may need to change the path to the .targets file to be in line with whatever version is installed on your build server.

Solution 3

There are multiple conditions that need to be meet in order to generate transforms correctly

Inside .csproj make sure you have all of the following:

<Project> ...

      <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
      <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.targets" />
      <Target Name="SetTransformAppConfigDestination" BeforeTargets="PrepareForBuild" Condition="exists('Web.$(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>
      <Target Name="TransformAppConfig" AfterTargets="PrepareForBuild" Condition="exists('Web.$(Configuration).config')">
        <TransformXml Source="Web.config" Transform="Web.$(Configuration).config" Destination="$(AppConfig)" />
      </Target>
    </Project>

Update your item group in .csproj file as well .

<ItemGroup> ...

<Content Include="Web.config">
      <SubType>Designer</SubType>
    </Content>
    <Content Include="Web.Debug.config">
      <DependentUpon>Web.config</DependentUpon>
    </Content>
    <Content Include="Web.Release.config">
      <DependentUpon>Web.config</DependentUpon>
      <IsTransformFile>True</IsTransformFile>
    </Content>
    <Content Include="Views\Web.config" />
    <Content Include="Views\Home\Index.cshtml" />
  </ItemGroup>

This will result in your config file to be nested in explorer view

enter image description here

Then make sure you have your path set correctly in properties -> build

enter image description here

Then add to your web.release.config tags for each node to be transformed

  1. xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"
  2. xdt:Transform="Replace"

to look like this:

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> 
   <appSettings xdt:Transform="Replace"> 
       <add key="VariableToBeTransformed" value="ValueToInsert"/> 
   </appSettings> 
   <system.web>
       <compilation xdt:Transform="RemoveAttributes(debug)" /> 
   </system.web>
</configuration> 

Also make sure your Solution configuration matches Debug/Release as intended enter image description here

Hope this helps everyone, you can do the same for app.config

Share:
17,438
jack
Author by

jack

Updated on July 21, 2022

Comments

  • jack
    jack almost 2 years

    We are setting up continuous integration with team city doing builds on check-ins. This works fine, however it always builds with default web.config, it does not transform with development environment specific web config. In Visual Studio, I have custom build configuration created for development. The web.development.config transforms correctly when I publish locally with development configuration selected, but this does not happen on the build server. In team city, as part of msbuild step I have created a build parameter sys.configuration and I am passing development as the value. But when it runs, the resulting web.config is not transformed with the development settings. I also tried setting the command line parameter to /p:configuration=development with no success.

    Any help will be much appreciated.

  • jack
    jack about 8 years
    This worked for me! Thanks for the help. All I did was, unload my project copied the above code to my project file. Note: By default "BeforeBuild" is commented.
  • MichaelMao
    MichaelMao almost 7 years
    This solution will change the original web.config so when you try to build the project in VS it would ask you to overwrite the web.config every time. In my opinion it's not acceptable.
  • Kevin Smith
    Kevin Smith about 6 years
    Oddly adding /p:Configuration=Release worked even though my publish profile is set to that too! Thanks!
  • Joe Lau
    Joe Lau over 5 years
    appending /p:Configuration=MyConfig works for me! Thanks!
  • baur
    baur over 2 years
    improved version: <TransformXml Source="Web.config" Transform="Web.$(Configuration).config" Destination="Web.config" Condition="Exists('Web.$(Configuration).config') AND '$(BuildingInsideVisualStudio)' != 'true'" />