Append figure 1 to the end of the file just before </Project>; v12.0 my change depending on your version of Visual Studio

Save .csproj and reload

Open configuration manager

Add a new Configuration Name: Base. Copy settings from: Release

Copy the contents of your web.config

Right click Web.Config > Add Config Transformation

Overwrite the web.base.config with the contents of your clipboard

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 -->

This comment has been minimized.

@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.)

@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.)

This comment has been minimized.

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 transformdoesn't exist for the current configuration: -->
<TargetName="_VisualStudioApplyTransform">
<!-- Transform the file out to a temp file, sourcing from our Web.config file: -->
<TransformXmlSource="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: -->
<CopySourceFiles="Web.config.temp"DestinationFiles="Web.config"Condition="Exists('Web.config.temp')" />
<!-- Cleanup after ourselves: -->
<DeleteFiles="Web.config.temp"Condition="Exists('Web.config.temp')" />
</Target>

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 transformdoesn't exist for the current configuration: -->
<TargetName="_VisualStudioApplyTransform">
<!-- Transform the file out to a temp file, sourcing from our Web.config file: -->
<TransformXmlSource="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: -->
<CopySourceFiles="Web.config.temp"DestinationFiles="Web.config"Condition="Exists('Web.config.temp')" />
<!-- Cleanup after ourselves: -->
<DeleteFiles="Web.config.temp"Condition="Exists('Web.config.temp')" />
</Target>

This comment has been minimized.

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?

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?