NuGet supports adding NuGet packages to Visual Studio project templates and item templates. When Visual Studio creates a project using a template that contains these NuGet packages, the resulting project will have these packages installed.
This is useful when you want your project/item template to reference a library(e.g. JSON.NET or EntityFramework). For example, project templates for ASP.NET MVC 3 include jQuery, Modernizr and other nuget packages.
This provides a better experience for end-users who can easily update the nuget packages installed by the project/item template long after the template has shipped. At the same time it makes it easier to author templates since you only need to reference one or more nuget packages instead of individual libraries.
Preinstalled packages work using template wizards. A special wizard gets invoked when the template gets instantiated. The wizard loads the list of packages that need to be installed and passes that information to the appropriate NuGet APIs.
The template needs to specify where to find the package nupkg files. Currently, three package repositories are supported:
2. Packages embedded inside of the project/item template itself
3. Packages installed on hard drive, with a registry key referencing the path
To add preinstalled packages to your project/item template you need to:
Edit your vstemplate file and add a reference to the NuGet template wizard by
<WizardExtension> <Assembly>NuGet.VisualStudio.Interop, Version=220.127.116.11, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</Assembly> <FullClassName>NuGet.VisualStudio.TemplateWizard</FullClassName> </WizardExtension>
NuGet.VisualStudio.Interop.dll is a new assembly that only contains the
TemplateWizard class. This class is a simple wrapper that calls into the actual implementation that lives in
NuGet.VisualStudio.dll. The assembly version will never change so that project/item templates continue to work with new versions of NuGet.
Add the list of packages to install in the project:
<WizardData> <packages> <package id="jQuery" version="1.6.2" /> </packages> </WizardData>
The wizard supports multiple
<package> elements. Both the
version attributes are required. An important consequence of this is that a specific version of a package will be installed even if a newer version
is available in the online package feed.
The reason for this behavior is that a future version of a package might introduce a change that is not compatible with the project/item template. The choice to upgrade the package to the latest version using NuGet is left to the developer who is in the best position to assume the risks of upgrading the package to the latest version.
Starting with NuGet 2.2.1, the wizard also supports multiple `
The remaining step is to specify the repository where NuGet can find the package files. As mentioned earlier, three package repository modes are supported:
The recommended approach for deploying Visual Studio project/item templates is through a VSIX package (read more about VSIX deployment here). The VSIX method is preferable because it allows you to package multiple project/item templates together and allows developers to easily discover your templates using the VS Extension Manager or the Visual Studio Gallery. On top of that you can easily push updates to your users using the Visual Studio Extension Manager automatic update mechanism.
To specify a VSIX as a package repository you modify the
<packages> element in the
<packages repository="extension" repositoryId="MyTemplateContainerExtensionId"> ... </packages>
repository attribute specifies the type of repository (“extension”) while
repositoryId is the unique identifier of your VSIX (i.e. the value of the
ID attribute in the extension’s vsixmanifest file).
Add your nupkg files as custom extension content in your
source.extension.vsixmanifest file. If you're using the 2.0 schema it should look like this:
Or if you're using the 1.0 schema it should look like this:
<Asset Type="Moq.4.0.10827.nupkg" d:Source="File" Path="Packages\Moq.4.0.10827.nupkg" d:VsixSubPath="Packages" />
<CustomExtension Type="Moq.4.0.10827.nupkg"> packages/Moq.4.0.10827.nupkg</CustomExtension>
Ensure that your
nupkg files are located under a folder called
Packages within the VSIX package.
You can place the nupkg files in the same VSIX as your project templates or you can have the packages be located in a separate VSIX if that makes more sense for your scenario ().
You should not reference VSIXs you do not have control over since they could change in the future and your project/item templates would break
If packaging multiple projects is not important to you (e.g. you are only distributing a single project/item template), a simpler but also more limited approach is to include the nupkg files in the project/item template zip file itself.
However, if you are bundling a set of project/item templates that relate to each other and share NuGet packages (e.g. you are shipping a custom MVC project template with versions for Razor, Web Forms, C#, and VB.NET), we do not recommend adding the NuGet packages directly to each project/item template zip file. It needlessly increases the size of the project/item template bundle.
To specify the project/item template as a package repository you modify the
<packages repository="template"> ... </packages>
repository attribute now has the value "template" and the
repositoryId attribute is not longer required. The nupkg files need to be placed into the root directory of the project/item template zip file.
Many SDKs are installed via MSI. These MSIs have the ability to install NuGet packages on disk for efficient package installation during project creation, avoiding the need to extract the packages during project creation. ASP.NET uses this approach for its preinstalled packages in project templates.
This approach requires a few moving parts:
Put the packages on disk during MSI installation
You can install only the nupkg files or the nupkg files along with their expanded contents.
If the expanded contents are also installed, this saves one additional step during project creation.
The file/folder format matches the standard packages folder used by NuGet where the nupkg files are all at the root and then each package has a subfolder with the id/version pair as the subfolder name.
Write a registry key that can be used to reference the package installation folder
Use HKEYLOCALMACHINE\SOFTWARE[\Wow6432Node]\NuGet\Repository for the key location.
The key name must be something unique to you. ASP.NET MVC 4 in VS 2012 uses "AspNetMvc4VS11" for instance.
The value must be the full path to your packages folder. ASP.NET MVC 4 uses "C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET MVC 4\Packages\" for instance.
Use the repository value of "registry" within the
Specifying your registry key name in the
If you have pre-unzipped your packages, use the
If you want to force a design time build at the end of packages installation, use
forceDesignTimeBuild="true"attribute. This attribute is supported on NuGet versions 3.2 and above.
Here's an example
<packages> element using the registry-specified folder repository:
<packages repository="registry" keyName="AspNetMvc4VS11" isPreunzipped="true"> <package id="EntityFramework" version="5.0.0" skipAssemblyReferences="true" /> ... </packages>
Note that the above example also uses the
skipAssemblyReferences="true" attribute, which is another performance
optimization. The VS template itself already includes this assembly reference, so we can tell NuGet to skip
adding assembly references from the package.
Make your VSIX declare a dependency on the NuGet VSIX by adding a reference to it in your VSIX manifest:
<Reference Id="NuPackToolsVsix.Microsoft.67e54e40-0ae3-42c5-a949-fddf5739e7a5" MinVersion="1.7.30402.9028"> <Name>NuGet Package Manager</Name> <MoreInfoUrl>http://docs.nuget.org/</MoreInfoUrl> </Reference> ....
Require project/item templates to be saved on creation by setting
<PromptForSaveOnCreation> in the
A sample project is available for you to get started. The source code is available here.