Project Templates and preinstalled NuGet packages
10/22 Update: This post was written before this feature became a part of NuGet.
This feature is now a part of NuGet and the latest version of this information can be found on the NuGet docs site.
There is also a sample project available.
Over the last few years the ASP.NET team has been including more and more libraries into the various project templates that we ship with Visual Studio and other products. The latest MVC 3 templates come with jQuery, jQuery UI, jQuery Validation, Modernizr, and Entity Framework. All this built-in functionality is great but one remaining snag is that upgrading all the packages by hand can be a pain. Of course the NuGet package manager is an excellent tool that solves the package upgrade problem but so far having project templates with preinstalled NuGet packages was not possible.
This post describes a new feature that will be shipping in NuGet 1.5: preinstalled NuGet packages. Since it is not documented anywhere at this time the purpose of this post is to describe how to create a VS project template with NuGet packages. If you play around with it please also provide feedback so we can make changes/improvements.
Authoring VS project templates is out of scope of this article but you can read more on how to create a project template directly using Visual Studio or using the Visual Studio SDK.
Adding packages to a project templates
NuGet 1.5 is not out yet but the feature has already been checked in and you can try it out by grabbing a recent NuGet preview build and installing the Visual Studio add-in (note that you might have to remove the previous version via the Extension Manager first).
Preinstalled packages work using project template wizards. A special wizard gets invoked when the project gets instantiated. The wizard loads the list of packages that need to be installed and passes that information to the appropriate NuGet APIs. The project template needs to specify where to find the package nupkg files. Currently two package repositories are supported:
- Packages embedded inside of a VSIX package.
- Packages embedded inside of the project template itself.
A frequent question is why not support downloading the nupkg files directly from https://nuget.org. We decided not to support such an option because users expect project templates to instantiate quickly and downloading files from the internet would slow things down. Also, it would not work on a plane or in other situations where a connection is not available.
To add preinstalled packages to your project template you need to:
Edit your vstemplate file and add a reference to the NuGet template wizard by adding a
WizardExtension
element:<WizardExtension> <Assembly>NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</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 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.4.4" /> </packages> </WizardData>
You can of course add multiple
<package>
elements. Both theid
andversion
attributes are required. You will notice that this means that a specific version of a package will be installed, even if a newer version is available in the online package feed. We cannot just update to the latest version because a future version of a package might introduce incompatibilities that would break an older version of the project template. It is up to the developer to upgrade using the package manager.
The remaining step is to specify the repository where NuGet can find the package files. As mentioned earlier, two package repository modes are supported:
VSIX package repository
The approach I recommend for deploying Visual Studio project 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 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 Extension Manager automatic update mechanism.
To specify a VSIX as a package repository you modify the
<package>
element:<packages repository="extension" repositoryId="MyTemplateExtension.46431780-a0c7-44e0-83c7-5dbd985f8e49"> ... </packages>
The 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).
You need to add your nupkg files as custom extension content and ensure that they 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 (just note that you should not reference VSIXs you do not have control over since they could change in the future and your project templates would break).
Template package repository
If packaging multiple projects is not important to you (e.g. you’re only distributing a single project template), a simpler but also more limited approach is to include the nupgk files in the project template zip file itself.
However, if you are bundling a set of project 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 template zip file. It needlessly increases the size of the project template bundle.
To specify the project template as a package repository you modify the
<package>
element:<packages repository="template"> ... </packages>
The 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 template.
Comments
Anonymous
August 22, 2011
Do you have a sample solution you can upload? ThanksAnonymous
October 10, 2011
Marcin, Would you be able to provide a sample VSIX for a project using a Nuget package with the VSIX package repository method? I been trying to get it to work for over a day now with no luck. I'm sure I am missing something simple. Also, I would love to see the download latest Nuget package functionality in the future. I am fully aware that this has the possibility of creating a broken project template but I think the convenience is worth the risk. Thanks, AndyAnonymous
October 18, 2011
I agree with gdandy. I've been trying to get it working locally myself with no luck. Once I create the template, install it, and start a new project with it, the nuget packages aren't pulled in. I've tried a few different mixes and no luck, so a full-on example would be really nice, as this is literally the only blog post on the Internet about adding nuget packages to templates. It's a really awesome feature that I'm wanting to use with ShoelaceMVC. Thanks for including this feature, it's an awesome one!Anonymous
October 22, 2011
Hi guys. Sorry it took so long. I've published a sample project that lets you build a VS extension that contains some simple templates that reference NuGet packages: bitbucket.org/.../nugetinvstemplatesAnonymous
March 19, 2012
Thanks, Marcin. I was actually talking about packages that are out on the NuGet gallery, like EntityFramework. For some reason I always get an error that it can't install. I'd like to be able to specify the packages my template requires, like EF 4.1, then when a user installs my vsix and creates a new project from the template, NuGet downloads the correct package from the gallery. What's the best way to do that? I'd rather not have to include the entire downloaded package in my vsix file and distribute it along with it unless that's the only way possible.Anonymous
March 26, 2012
Agree with Ryan. I need a way for my template to automatically download the packages from the gallery. Bundling everything locally can be a fallback option, not the only one!Anonymous
March 26, 2012
Ryan, Hrusikesh. Please file feature requests on the NuGet codeplex site: http://nuget.codeplex.com