Transforming source code and configuration files
A source code transformation applies one-way token replacement to files in the package's content
or contentFiles
folder (content
for customers using packages.config
and contentFiles
for PackageReference
) when the package is installed, where tokens refer to Visual Studio project properties. This allows you to insert a file into the project's namespace, or to customize code that would typically go into global.asax
in an ASP.NET project.
A config file transformation allows you to modify files that already exist in a target project, such as web.config
and app.config
. For example, your package might need to add an item to the modules
section in the config file. This transformation is done by including special files in the package that describe the sections to add to the configuration files. When a package is uninstalled, those same changes are then reversed, making this a two-way transformation.
Specifying source code transformations
Files that you want to insert from the package into the project must be located within the package's
content
andcontentFiles
folders. For example, if you want a file calledContosoData.cs
to be installed in aModels
folder of the target project, it must be inside thecontent\Models
andcontentFiles\{lang}\{tfm}\Models
folders in the package.To instruct NuGet to apply token replacement at install time, append
.pp
to the source code file name. After installation, the file will not have the.pp
extension.For example, to make transformations in
ContosoData.cs
, name the file in the packageContosoData.cs.pp
. After installation it will appear asContosoData.cs
.In the source code file, use case-insensitive tokens of the form
$token$
to indicate values that NuGet should replace with project properties:namespace $rootnamespace$.Models { public struct CategoryInfo { public string categoryid; public string description; public string htmlUrl; public string rssUrl; public string title; } }
Upon installation, NuGet replaces
$rootnamespace$
withFabrikam
assuming the target project's whose root namespace isFabrikam
.
The $rootnamespace$
token is the most commonly used project property; all others are listed in project properties. Be mindful, of course, that some properties might be specific to the project type.
Specifying config file transformations
As described in the sections that follow, config file transformations can be done in two ways:
- Include
app.config.transform
andweb.config.transform
files in your package'scontent
folder, where the.transform
extension tells NuGet that these files contain the XML to merge with existing config files when the package is installed. When a package is uninstalled, that same XML is removed. - Include
app.config.install.xdt
andweb.config.install.xdt
files in your package'scontent
folder, using XDT syntax to describe the desired changes. With this option you can also include a.uninstall.xdt
file to reverse changes when the package is removed from a project.
Note
Transformations are not applied to .config
files referenced as a link in Visual Studio.
The advantage of using XDT is that instead of simply merging two static files, it provides a syntax for manipulating the structure of an XML DOM using element and attribute matching using full XPath support. XDT can then add, update, or remove elements, place new elements at a specific location, or replace/remove elements (including child nodes). This makes it straightforward to create uninstall transforms that back out all transformations done during package installation.
XML transforms
The app.config.transform
and web.config.transform
in a package's content
folder contain only those elements to merge into the project's existing app.config
and web.config
files.
As an example, suppose the project initially contains the following content in web.config
:
<configuration>
<system.webServer>
<modules>
<add name="ContosoUtilities" type="Contoso.Utilities" />
</modules>
</system.webServer>
</configuration>
To add a MyNuModule
element to the modules
section during package install, create a web.config.transform
file in the package's content
folder that looks like this:
<configuration>
<system.webServer>
<modules>
<add name="MyNuModule" type="Sample.MyNuModule" />
</modules>
</system.webServer>
</configuration>
After NuGet installs the package, web.config
will appear as follows:
<configuration>
<system.webServer>
<modules>
<add name="ContosoUtilities" type="Contoso.Utilities" />
<add name="MyNuModule" type="Sample.MyNuModule" />
</modules>
</system.webServer>
</configuration>
Notice that NuGet didn't replace the modules
section, it just merged the new entry into it by adding only new elements and attributes. NuGet will not change any existing elements or attributes.
When the package is uninstalled, NuGet will examine the .transform
files again and remove the elements it contains from the appropriate .config
files. Note that this process will not affect any lines in the .config
file that you modify after package installation.
As a more extensive example, the Error Logging Modules and Handlers for ASP.NET (ELMAH) package adds many entries into web.config
, which are again removed when a package is uninstalled.
To examine its web.config.transform
file, download the ELMAH package from the link above, change the package extension from .nupkg
to .zip
, and then open content\web.config.transform
in that ZIP file.
To see the effect of installing and uninstalling the package, create a new ASP.NET project in Visual Studio (the template is under Visual C# > Web in the New Project dialog), and select an empty ASP.NET application. Open web.config
to see its initial state. Then right-click the project, select Manage NuGet Packages, browse for ELMAH on nuget.org, and install the latest version. Notice all the changes to web.config
. Now uninstall the package and you see web.config
revert to its prior state.
XDT transforms
Note
As mentioned in the package compatibility issues section of the docs for migrating from packages.config
to PackageReference
, XDT transformations as described below are only supported by packages.config
. If you add the below files to your package, consumers using your package with PackageReference
will not have the transformations applied (refer to this sample to make XDT transforms work withPackageReference
).
You can modify config files using XDT syntax. You can also have NuGet replace tokens with project properties by including the property name within $
delimiters (case-insensitive).
For example, the following app.config.install.xdt
file will insert an appSettings
element into app.config
containing the FullPath
, FileName
, and ActiveConfigurationSettings
values from the project:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings xdt:Transform="Insert">
<add key="FullPath" value="$FullPath$" />
<add key="FileName" value="$filename$" />
<add key="ActiveConfigurationSettings " value="$ActiveConfigurationSettings$" />
</appSettings>
</configuration>
For another example, suppose the project initially contains the following content in web.config
:
<configuration>
<system.webServer>
<modules>
<add name="ContosoUtilities" type="Contoso.Utilities" />
</modules>
</system.webServer>
</configuration>
To add a MyNuModule
element to the modules
section during package install, the package's web.config.install.xdt
would contain the following:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<modules>
<add name="MyNuModule" type="Sample.MyNuModule" xdt:Transform="Insert" />
</modules>
</system.webServer>
</configuration>
After installing the package, web.config
will look like this:
<configuration>
<system.webServer>
<modules>
<add name="ContosoUtilities" type="Contoso.Utilities" />
<add name="MyNuModule" type="Sample.MyNuModule" />
</modules>
</system.webServer>
</configuration>
To remove only the MyNuModule
element during package uninstall, the web.config.uninstall.xdt
file should contain the following:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<modules>
<add name="MyNuModule" xdt:Transform="Remove" xdt:Locator="Match(name)" />
</modules>
</system.webServer>
</configuration>