Instantly share code, notes, and snippets.

Embed
What would you like to do?
How to enable transformations on build with Visual Studio

#Transform web.config on build

  1. Unload the project
  2. Edit .csproj
  3. Append figure 1 to the end of the file just before </Project>; v12.0 my change depending on your version of Visual Studio
  4. Save .csproj and reload
  5. Open configuration manager
  6. Add a new Configuration Name: Base. Copy settings from: Release
  7. Copy the contents of your web.config
  8. Right click Web.Config > Add Config Transformation
  9. Overwrite the web.base.config with the contents of your clipboard
  10. From now on Web.Config will be overwritten using transformations.

For settings that apply to all cofigurations use Base
For settings that apply only to Release use Release
For settings that apply only to Debug use Debug

A helpful note to add to your projects [base|debug|release].config

<!-- WEB CONFIG IN THIS PROJECT SHOULD ONLY BE MODIFIED BY -->
<!-- web.base.config -->
<!-- web.debug.config -->
<!-- web.release.config -->
<!-- CHANGES MADE DIRECTLY TO THE web.config WILL BE OVERWRITTEN -->

####Figure 1 Copy and paste:

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

This comment has been minimized.

stimpy77 commented Mar 25, 2015

Found this from the Googlz. Pithy, brief, concise, well-formed, .. bravo.

@stimpy77

This comment has been minimized.

stimpy77 commented Mar 25, 2015

FYI someone said elsewhere (I haven't validated) that in VS2013 (and/or perhaps .NET 4.5.x) you don't need the <Import ..> tag addition.

@andriy-f

This comment has been minimized.

andriy-f commented May 29, 2015

Threre are some NuGet packages that are modifying Web.config directly. In this case it's important not to forget to copy those changes to Web.base.config

@stimpy77

This comment has been minimized.

stimpy77 commented Jul 14, 2015

Automating and putting into nested folder. Thanks again. https://github.com/stimpy77/FastKoala

@educit

This comment has been minimized.

educit commented Feb 23, 2016

I used Visual Studio 2015 and as stimpy77 said we don't need the <Import ...> tag addition.
Instead it will likely be located under this:

@JohnLBevan

This comment has been minimized.

JohnLBevan commented Jul 16, 2016

FYI: To have this applied during the build rather than deploy phase, use the Slow Cheetah plugin; more info here: http://stackoverflow.com/a/8841094/361842

@nordquist

This comment has been minimized.

nordquist commented Jul 26, 2016

Why use base? The following should work just fine:
<TransformXml Source="Web.config" Transform="Web.$(Configuration).config" Destination="Web.config" />

@glcheetham

This comment has been minimized.

glcheetham commented Aug 8, 2016

@nordquist you should use Web.config.base so that you're not committing the Web.config with the (potentially sensitive) transforms into source control

@wilson0x4d

This comment has been minimized.

wilson0x4d commented Sep 17, 2016

@nordquist yeah it's a nifty trick, but i'd ditch the web.base.config too -- it's abnormal, obtuse, and a solves a pebkac problem by introducing something abnormal, obtuse.. "be a rebel, conform;" i say. the existing industry convention is to have a default, and then transform the default for a particular environment/config/purpose. the default configs live in source control, don't require a build step to exist or be valid, and typically meet the needs of local hosting/debugging (e.g. valid for all developers that would need to punch F5 "out of the box" and expect everything to work.)

@zleao

This comment has been minimized.

zleao commented Oct 20, 2016

Fast and helpful help to achieve web.config transformation on build! Thank you!

@ivanpointer

This comment has been minimized.

ivanpointer commented Nov 11, 2016

I think the main problem with transforming the Web.config file directly, is that the file handle is still open by the TransformXml task for read, when it tries to write it. The solution, is to add an extra copy (and delete) step in, to avoid the file handle collision:

  <!-- First, we extend the "BuildDependsOn" property with our custom target for applying the transform.
This is a cleaner/safer alternative to overloading the "AfterBuild" target: -->
  <PropertyGroup>
    <BuildDependsOn>
      $(BuildDependsOn);
      _VisualStudioApplyTransform;
    </BuildDependsOn>
  </PropertyGroup>

  <!-- Now, down to business: this is our target for applying the config transform.
I've included some conditions, to help avoid the build from blowing up when a transform
doesn't exist for the current configuration: -->

  <Target Name="_VisualStudioApplyTransform">
    <!-- Transform the file out to a temp file, sourcing from our Web.config file: -->
    <TransformXml Source="Web.config" Transform="Web.$(Configuration).config" Destination="Web.config.temp"
                  Condition="Exists('Web.$(Configuration).config')" />

    <!-- Copy the temp file, back over the top of Web.config, the file handle opened by TransformXml is closed now: -->
    <Copy SourceFiles="Web.config.temp" DestinationFiles="Web.config"
          Condition="Exists('Web.config.temp')" />

    <!-- Cleanup after ourselves: -->
    <Delete Files="Web.config.temp" Condition="Exists('Web.config.temp')" />
  </Target>
@urig

This comment has been minimized.

urig commented Feb 13, 2017

First off, thanks for sharing this. It's awesome.
Does this "play nice" with "publish time" config transforms? Having applied @stimpy77's https://github.com/stimpy77/FastKoala to a project, it looks to me that the transforms are not running when right-clicking the project and publishing it to Azure. Is there something I'm missing?

@cssmonauts

This comment has been minimized.

cssmonauts commented Mar 3, 2017

In VS Community Update 3, I get an "invalid child element" for TransformXml when using this verbatim... I also tried:

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\WebApplications\Microsoft.WebApplication.targets" />

to see if that made a difference, but it didn't. I can't seem to find any answers online! Anyone getting the same issue?

@resnyanskiy

This comment has been minimized.

resnyanskiy commented Mar 21, 2017

FYI, https://marketplace.visualstudio.com/items?itemName=GolanAvraham.ConfigurationTransform
Based on <UsingTask> element, could be used with .xproj file.

@cemerson

This comment has been minimized.

cemerson commented Mar 19, 2018

Awesome thanks for sharing. My VS 2015 version of this (I changed Source to just "Web.config" as I didn't have a "base" version:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v14.0\WebApplications\Microsoft.WebApplication.targets" /> <Target Name="BeforeBuild"> <TransformXml Source="Web.config" Transform="Web.$(Configuration).config" Destination="Web.config" /> </Target>

@valbers

This comment has been minimized.

valbers commented Apr 5, 2018

Thank you. Small correction:
"might change"
https://gist.github.com/valbers/2635267ef83cf976c7fc4b4beb516087

@mrpmorris

This comment has been minimized.

mrpmorris commented May 11, 2018

This is great, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment