Visual Studio (2010 - 2019) does unfortunately not directly support it while you are debugging, it is only intended for publishing - even with the extension SlowCheetah (marked answer) it does not work for me (only for projects using app.config rather than web.config).
Note that there is a workaround described at codeproject.
It describes how to modify the .msproj file to overwrite the current web.config by the transformed version.
I will first describe that workaround as Option 1, but I have recently found out another Option 2, which is easier to use (so you may scroll down to option 2 directly if you like):
Option 1: I have added the instructions taken from the original codeproject article (see the link above), because the screen shots there are already gone, and I don't want to lose the entire information:
VS.Net doesn't do any transforming when you are developing and just debugging your local environment. But there are some steps you can do to make this happen if you want.
- First, create the configurations you want in VS.Net, assuming the default debug and release are not enough for what you are trying to accomplish.
- Right click on your
web.config
and select Add Config Transforms - this will create a dependant transformation config for each of your configurations defined.
- Now you can rename your
web.config
to web.base.config
.
- Add a
web.config
to your project. It doesn't matter what is in it because it will get overwritten every time we do a build but we want it part of the project so VS.Net doesn't give us the "Your Project isn't configured for Debugging" pop-up.
- Edit your
.csproj
Project File and add the following TransformXml
task to the AfterBuild target. Here you can see I will be transforming the web.base.config
file using the web.[configuration].config
and it will save it as web.config
. For details, please check this Microsoft Q&A, and for instructions how to extend the build, look there.
Option 2:
Based on this answer, I have developed a simple console app, TransformConfig.exe (in C# 6.0 syntax):
using System;
using System.Linq;
using Microsoft.Web.XmlTransform;
namespace TransformConfig
{
class Program
{
static int Main(string[] args)
{
var myDocumentsFolder = $@"C:\Users\{Environment.UserName}\Documents";
var myVsProjects = $@"{myDocumentsFolder}\Visual Studio 2015\Projects";
string srcConfigFileName = "Web.config";
string tgtConfigFileName = srcConfigFileName;
string transformFileName = "Web.Debug.config";
string basePath = myVsProjects + @"\";
try
{
var numArgs = args?.Count() ?? 0;
if (numArgs == 0 || args.Any(x=>x=="/?"))
{
Console.WriteLine("\nTransformConfig - Usage:");
Console.WriteLine("\tTransformConfig.exe /d:tgtConfigFileName [/t:transformFileName [/s:srcConfigFileName][/b:basePath]]");
Console.WriteLine($"\nIf 'basePath' is just a directory name, '{basePath}' is preceeded.");
Console.WriteLine("\nTransformConfig - Example (inside PostBuild event):");
Console.WriteLine("\t\"c:\\Tools\\TransformConfig.exe\" /d:Web.config /t:Web.$(ConfigurationName).config /s:Web.Template.config /b:\"$(ProjectDir)\\\"");
Environment.ExitCode = 1;
return 1;
}
foreach (var a in args)
{
var param = a.Trim().Substring(3).TrimStart();
switch (a.TrimStart().Substring(0,2).ToLowerInvariant())
{
case "/d":
tgtConfigFileName = param ?? tgtConfigFileName;
break;
case "/t":
transformFileName = param ?? transformFileName;
break;
case "/b":
var isPath = (param ?? "").Contains("\\");
basePath = (isPath == false)
? $@"{myVsProjects}\" + param ?? ""
: param;
break;
case "/s":
srcConfigFileName = param ?? srcConfigFileName;
break;
default:
break;
}
}
basePath = System.IO.Path.GetFullPath(basePath);
if (!basePath.EndsWith("\\")) basePath += "\\";
if (tgtConfigFileName != srcConfigFileName)
{
System.IO.File.Copy(basePath + srcConfigFileName,
basePath + tgtConfigFileName, true);
}
TransformConfig(basePath + tgtConfigFileName, basePath + transformFileName);
Console.WriteLine($"TransformConfig - transformed '{basePath + tgtConfigFileName}' successfully using '{transformFileName}'.");
Environment.ExitCode = 0;
return 0;
}
catch (Exception ex)
{
var msg = $"{ex.Message}\nParameters:\n/d:{tgtConfigFileName}\n/t:{transformFileName}\n/s:{srcConfigFileName}\n/b:{basePath}";
Console.WriteLine($"TransformConfig - Exception occurred: {msg}");
Console.WriteLine($"TransformConfig - Processing aborted.");
Environment.ExitCode = 2;
return 2;
}
}
public static void TransformConfig(string configFileName, string transformFileName)
{
var document = new XmlTransformableDocument();
document.PreserveWhitespace = true;
document.Load(configFileName);
var transformation = new XmlTransformation(transformFileName);
if (!transformation.Apply(document))
{
throw new Exception("Transformation Failed");
}
document.Save(configFileName);
}
}
}
Ensure that you add the DLL "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.XmlTransform.dll"
as a reference (this example applies to VS 2015, for older versions replace the v14.0
in the path by the appropriate version number, e.g. v11.0
).
For Visual Studio 2017, the naming schema for the path has changed: For example, for the enterprise version it is here: C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft\VisualStudio\v15.0\Web
.
I assume that for the professional version you need to replace Enterprise
in the path by Professional
. If you're using the preview version, additionally replace 2017
by Preview
.
Here's an overview how the path has changed for different versions of Visual Studio (if you don't have the Enterprise version you might need to replace Enterprise
by Professional
in the path):
VS Version Path (for Microsoft.Web.XmlTransform.dll
)
2015 C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web
2017 C:\Program Files (x86)\Microsoft Visual Studio\2017\
Enterprise\MSBuild\Microsoft\VisualStudio\v15.0\Web
2019 C:\Program Files (x86)\Microsoft Visual Studio\2019\
Enterprise\MSBuild\Microsoft\VisualStudio\v16.0\Web
Compile it and put the .exe file into a directory, e.g. C:\MyTools\
.
Usage:
You can use it in your post build event (in project properties, select Build Events, then edit the Post-build event command line). Commandline parameters are (example):
"C:\MyTools\TransformConfig.Exe" /d:Web.config /t:Web.$(ConfigurationName).config /s:Web.Template.config /b:"$(ProjectDir)\"
i.e. first the name of the config file, followed by the transform config file, followed by an optional template config, followed by the path to your project containing both files.
I have added the optional template config parameter because otherwise your original complete config would be overwritten by the transform, which can be avoided by providing a template.
Create the template by simply copying the original Web.config and name it Web.Template.config.
Note:
If you prefer, you can also copy the TransformConfig.exe
file to the Visual Studio path mentioned above where the Microsoft.Web.XmlTransform.dll
resides and refer to it in all your projects where you need to transform your configs.
For those of you who are wondering why I added Environment.ExitCode = x;
assignments: Simply returning an int from Main did not help in the build event. See details here.
If you're publishing your project and you're using a Web.Template.config, ensure that you did a rebuild on your solution with the right configuration (usually Release) before you publish. The reason is that the Web.Config is overwritten during debugging and you might end up transforming the wrong file otherwise.