November 2011

Volume 26 Number 11

NuGet - Manage Project Libraries with NuGet

By Phil Haack | November 2011

Try as it might, Microsoft can’t supply every possible library developers need. Though Microsoft employs close to 90,000 people worldwide, the world has millions of developers. It doesn’t make sense for Microsoft to attempt to fill every niche, nor does it scale. Developers, therefore, frequently take it upon themselves to “scratch their own itch,” and they’ve written thousands upon thousands of useful libraries that are distributed all over the Web.

The problem with so many libraries out there is sharing them. Sharing and reusing code is a big challenge. Don’t believe me? Walk into any midsize to large shop and ask them how many logging libraries they have. Visit enough companies and you’ll find a high percentage of in-house logging libraries when good ones—Log4Net, NLog and Error Logging Modules and Handlers, or ELMAH—already exist.

When a developer starts a new project, he faces the empty canvas problem. How can he find these useful libraries? How does he incorporate a library into his current project and manage its dependencies and updates?

ELMAH is a great example of a useful library that developers took upon themselves to write. ELMAH logs all unhandled exceptions within a Web application along with all the request information, such as headers, server variables and so on, when the exception is thrown. Suppose you’ve just heard about ELMAH and want to use it in your next project.

These are the steps you might take:

  1. Find ELMAH. Due to its unique name, a Bing search locates the ELMAH Google code page as the first result.
  2. Download the correct zip package. The download page for the site has multiple zip packages. You have to think about it and pick the correct one. Sometimes the correct choice isn’t intuitive.
  3. “Unblock” the package. Once you’ve downloaded the package from the Web, you need to right-click the file, bring up the Properties dialog and click the Unblock button to remove the “mark of the Web” from the file.
  4. Verify its hash against the one provided by the hosting environment. The Google code site displays a QR code representing the zip file. How many developers do you know who take the time to verify the file against the QR code?
  5. Unzip the package contents into a specific location in the solution. Most developers avoid unpacking assemblies into the bin directory, because the directory is meant for output from the build, not for input, and isn’t tracked by version control. Instead, it’s important to add the dependency to a folder that’s committed to version control and reference the assembly from that location.
  6. Add an assembly reference to the project. The assembly isn’t usable until you add a reference to it from within the Visual Studio project.
  7. Update web.config with the correct settings. This may mean more searching around using Bing or Google  while you try to find the correct settings needed for your config file.

What a pain! Now suppose you have to do this for 10 to 15 dependencies. When it comes time to release the next version of your application, you spend significant time searching for updates to your application’s dependencies.

That often-maligned notion, “not invented here” (NIH), begins to sound like a good idea.

NuGet to the Rescue

NuGet is a Visual Studio extension that makes it easy to add, update and remove libraries (deployed as packages) in a Visual Studio project. A NuGet package is a set of files packaged up into a single file with the .nupkg extension using the Open Packaging Conventions (OPC) format.

OPC is just a fancy acronym for a zip file with some metadata. In fact, you’re probably already familiar with OPC, as it’s the format used by Word and Excel documents. If you’ve ever taken a .docx file and changed the file extension to .zip, you know you can open it up and poke around its internals. The same goes for .nupkg files.

The NuGet product also comes with utilities to easily create and publish packages. For now, I’ll focus on using NuGet to discover and install packages. Later I’ll cover how to create and publish packages.

Installing NuGet

To install NuGet, launch the Visual Studio Extension Manager via the Tools | Extension Manager menu option. Click the Online Gallery tab to view available Visual Studio extensions, as shown in Figure 1. As you can see, NuGet is the highest-ranked package, which puts it on the first screen. If that ever changes, you can use the search box on the top right to find it. Click the Download button to install NuGet.

Visual Studio Extension Manager
Figure 1 Visual Studio Extension Manager

If you’ve installed ASP.NET MVC 3, you already have NuGet installed. ASP.NET MVC 3 includes NuGet, and Microsoft plans to include NuGet in the next version of Visual Studio.

Installing a Package

Let’s start with NuGet’s user-friendly dialog to install packages. NuGet also comes with a Windows PowerShell-based console geared toward power users that I’ll cover later.

To launch NuGet, right-click on the project’s references node and select the Manage NuGet Packages option (this option had a different label prior to NuGet 1.4). This launches the Manage NuGet Packages dialog shown in Figure 2.

NuGet Package Manager Dialog
Figure 2 NuGet Package Manager Dialog

Make sure the Online tab is selected and type in a search term in the top right (for example, search for MiniProfiler, a useful library from the StackOverflow.com folks).

Once you locate a package, click the Install button to install the package. NuGet then downloads the package and its dependencies and applies any necessary changes to your project specified by the packages.

NuGet performs the following steps to install a package:

  1. Downloads the package file and all its dependencies. Some packages require explicit license acceptance and prompt the user to accept the license terms for the package. 
Most packages are fine with implicit license acceptance and do not prompt. If the package already exists in the solution or in the local machine cache, NuGet skips downloading the package.
  2. Extracts the package’s contents. NuGet extracts the contents into the packages folder, creating the folder if necessary. The packages folder is located next to your solution (.sln) file. If the same package is installed into multiple projects within a solution, the package is only extracted once and is shared by each project.
  3. References assemblies in the package. By convention, NuGet updates the project to reference the appropriate assembly (or assemblies) within the packages lib folder. For example, when installing a package into a project targeting the Microsoft .NET Framework 4, NuGet will add references to assemblies within the lib/net40 folder.
  4. Copies content into the project. By convention, NuGet copies the package’s content folder’s contents into the project. This is useful for packages containing JavaScript files or images.
  5. Applies package transformations. If any package contains transform files, such as app.config.transform or web.config.transform for config, NuGet applies those transformations before it copies the content. Some packages may contain source code that can be transformed to include the current project’s namespace in the source file. NuGet transforms those files as well.
  6. Runs associated Windows PowerShell scripts in the package. Some packages may contain Windows PowerShell scripts that automate Visual Studio using the Design Time Environment (DTE) to handle tasks NuGet isn’t designed for.

After NuGet performs all these steps, the library is ready for use. Many packages wire themselves up using the WebActivator package to minimize any configuration necessary after installation.

A package can be uninstalled, which returns your project to the state it was in before installing the package.

Updating Packages

In his book, “Facts and Fallacies of Software Engineering” (Addison-Wesley Professional, 2002), Robert L. Glass states: “Maintenance typically consumes about 40 to 80 percent (60percent average) of software costs. Therefore, it is probably the most important lifecycle phase.”

Installing a package is only the beginning of the story. Over time, as these libraries are maintained, it becomes important to keep your application up-to-date with the latest bug fixes for the libraries. This requires you to answer the question, “Which dependencies in this project have new updates available?”

As mentioned before, answering this question has always been a time-consuming endeavor. With NuGet, however, you simply launch the 
dialog and click on the Updates tab to see a list of packages with available updates, as shown in Figure 3. Click the Update button to update the package to the latest version.

Updates Available for the Current Project
Figure 3 Updates Available for the Current Project

The update command uninstalls the old package and then installs the new one, ensuring all dependencies are updated appropriately if needed.

NuGet provides commands in the Package Manager Console to better control updates—such as to update all packages in the solution or to perform a “safe” update, for example.

NuGet for Power Users

While I’m a big fan of nice GUI dialogs, I know many developers who disdain mouse-dragging people like me. Those folks prefer a command-line 
shell as the UI for its ability to compose sets of commands together.

NuGet fills this need with a Windows PowerShell-based console window called the Package Manager Console, as well as a set of Windows PowerShell commands for interacting with NuGet. Windows PowerShell, a .NET-based scripting language and command-line shell, is well-suited for composing command sets and working with objects.

To launch the Package Manager Console, navigate to the Tools | Library Package Manager | Package Manager Console menu option.

Listing and Installing Packages

To list and search for packages, use the Get-Package command. By default, the command lists installed packages in the current project. You can search for packages online by specifying the ListAvailable flag combined with the Filter flag. The following command searches for all packages mentioning “MVC”:

Get-Package -ListAvailable -Filter Mvc

Once you find a package to install, use the Install-Package command. For example, to install ELMAH into the current project:

Install-Package Elmah

Because Windows PowerShell is a dynamic language, it can provide tab expansions to help you correctly enter command arguments. Tab expansions are equivalent to IntelliSense for C# but, unlike IntelliSense, which is based on compile-time information, tab expansions can be populated at run time.

For example, if you type in Install-Package Mvc{tab}, you’ll see a list of possible package names from the package source, as shown in Figure 4.

A Tab-Expanded List of Packages
Figure 4 A Tab-Expanded List of Packages

Updating Packages

The Package Manager Console also includes a command that provides more control over updates than the dialog. For example, call this command with no arguments to update every package in every project of the solution:

Update-Package

This command attempts to update each package to the latest version. Thus, if you have version 1.0 of a package and versions 1.1 and 2.0 are available in the package source, this command will update the package to version 2.0, because it’s the latest.

This can be a drastic action if any package contains breaking changes. In many cases, you’ll just want to update every package to the latest bug fix release. This is called a “safe” update and assumes that packages with a larger build or revision number (but with the same major and minor numbers) are backward-compatible. Just add the Safe flag to perform a safe update, like so:

Update-Package -Safe

In this case, if you have version 1.0.0 of a package installed, and both 1.0.1 and 1.1 are available in the package source, the package is safely upgraded to 1.0.1 and not 1.1.

The Update-Package command also provides more granularity, such as updating a package to a specific version of the package rather than the latest version.

Extending Visual Studio with New Commands

While the ability to use Windows PowerShell to install packages is nice, it’s not the most compelling reason to choose Windows PowerShell. One of the most compelling reasons is that packages can add new commands to the Package Manager Console. These commands can interact with the Visual Studio DTE in order to perform various tasks.

For example, install the MvcScaffolding package and it adds a new Scaffold Controller command to the console. Given an Entity Framework (EF) Code First object, this command generates a controller, controller actions and views corresponding to the basic Create, Read, Update and Delete (CRUD) operations for the EF object, as seen in Figure 5.

MvcScaffolding Custom Scaffold Command in Action
Figure 5 MvcScaffolding Custom Scaffold Command in Action

NuGet in Your Organization

With all this focus on how NuGet makes it easy to share libraries with the public developer community, NuGet’s usefulness within the enterprise is easy to miss.

After all, there’s nothing special about businesses that make them immune to the same challenges the software community as a whole faces when sharing code. As a company grows over time, entropy sets in. Different groups within the same company use their own private versions of company “standard” libraries. Some groups may go so far as to completely ignore these libraries and write their own from scratch.

Often, the problem is not the libraries themselves but the hassle in sharing these libraries with other teams and keeping them notified of changes. Sound familiar?

Package Sources

So far, I’ve covered how to install packages, but haven’t answered the obvious question: Where are those packages located? They’re located in the official NuGet package gallery at nuget.org. This gallery exposes an OData feed: packages.nuget.org/v1/FeedService.svc.

The OData format allows the NuGet client to generate ad hoc queries to search the package source on the client, but have them executed on the server.

To add more package sources to NuGet, navigate to the Tools | Library Package Manager | Package Manager Settings menu option and click on the Package Sources node, as seen in Figure 6.

Package Manager Settings
Figure 6 Package Manager Settings

The default package source is an OData endpoint on the Web, but the example screenshot also shows a local folder as a package source. NuGet treats folders (whether local or on a network share) as a package source and lists each package within the folder in the Online pane. This makes sharing code with others as easy as putting it in a folder, and is also helpful when you test packages you create yourself.

Hosting Your Own NuGet Server

In addition to hosting packages on a network share, you can also set up a Web site as a package source and use it to share packages with others across your organization.

As with many tasks, there’s a package that helps here. First, create an empty ASP.NET Web Application in Visual Studio (targeting ASP.NET 4). Use NuGet to install the package NuGet.Server. This package adds a simple OData endpoint to the empty Web application.

Next, add package files to the Web application’s Packages folder to publish them and deploy the Web site. For more details on how to set this up, refer to the NuGet documentation site, bit.ly/jirmLO.

For those who want to deploy a full gallery experience like nuget.org, the NuGet gallery code is also available as an open source project via the nugetgallery.codeplex.com project.

Hosting a private NuGet server or gallery implementation is an easy way to share proprietary code within a company without having to publish it to the public.

Creating a Package

NuGet wouldn’t be useful without any packages to install in the first place. The more useful packages available in NuGet, the more valuable NuGet becomes to every developer. That’s why the NuGet team has gone to great lengths to make creating packages as simple and painless as possible. While it’s easy to create a package, the NuGet team continues to invest in features to make it even simpler. They’ve built several tools for creating NuGet packages. For example, Package Explorer is a ClickOnce application written by a developer on the NuGet team that provides a visual way to build or examine a package. It’s available at npe.codeplex.com.

NuGet.exe

Because most package authors want to integrate package creation into their build processes, let’s look at another approach that uses the NuGet command-line utility. You’ll need to download the utility just once from bit.ly/gmw54b. After you download NuGet.exe, make sure to put it in a folder that’s added to your PATH environment variable. I have a folder named “utils” for utilities like this.

The reason I say you only need to download NuGet.exe once (well, once per machine) is because it’s a self-updating executable. Just run the following command to have NuGet check online and update itself to the latest version if a newer one is available:

nuget update –self

The command-line tool can query the online feed like the Package Manager Console. For example, to search for all packages with “MVC,” use the following command:

nuget list Mvc

NuGet.exe can even download a package and dependencies and unpack them, but it can’t modify a project to reference the downloaded package assemblies or run any Windows PowerShell scripts included in a package.

Creating a Package from a Project

Packages contain a single assembly 90 percent of the time (a statistic I made up). This section covers a simple workflow to create such packages using NuGet.exe against a project file (such as a .csproj or .vbproj file).

For details on creating more complex packages, such as a single package that targets different .NET Framework versions, refer to the NuGet documentation Web site at docs.nuget.org.

The basic steps for creating a package are:

  1. Create a class library project.
  2. Generate a NuSpec manifest from the project.
  3. Update the project’s assembly metadata.
  4. Use NuGet.exe to create the package.

Create a Class Library Project To share an assembly, start with a class library project. NuGet can pack multiple project types, but the most common case when sharing code is to use a class library. After you create the package, make sure to open the AssemblyInfo.cs file to update the assembly’s metadata.

Create a NuSpec Manifest The NuSpec file is a package manifest with important metadata about the package, such as the author, description and the package dependencies. The NuSpec format is simple to create by hand, but it’s more convenient to let the spec command generate the file for you. Make sure to run the command in the same directory as the project file:

nuget spec

In this particular case, because the spec command generated the NuSpec from a project file, it contains placeholders for some metadata, as shown in Figure 7.

Figure 7 The Generated NuSpec File

<?xml version="1.0"?>
<package xmlns=
  "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <title>$title$</title>
    <authors>$author$</authors>
    <owners>$author$</owners>
    <licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
    <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>$description$</description>
    <copyright>Copyright 2011</copyright>
    <tags>Tag1 Tag2</tags>
  </metadata>
</package>

Don’t edit the fields with the placeholders, but do fill in the correct values for the other fields such as licenseUrl, projectUrl, iconUrl and tags.

Update the Project’s Assembly Metadata Every assembly has metadata related to the assembly. NuGet can read this assembly metadata and merge it into the NuSpec manifest when it creates a package, which ensures this information is never out of sync between your package and your assembly.

As mentioned earlier, this information is usually located in a file named AssemblyInfo.cs. The table in Figure 8 shows the mappings between the assembly metadata and the NuSpec placeholder values.

Figure 8 Assembly Metadata Mapped to NuSpec

Token Source
$id$ The assembly name.
$title$ The assembly title as specified in the AssemblyTitleAttribute.
$version$ The assembly version as specified in the assembly’s AssemblyVersionAttribute.
$author$ The company as specified in the AssemblyCompanyAttribute.
$description$ The description as specified in the AssemblyDescriptionAttribute.

Unlike the other fields, the $id$ field is not extracted from an assembly attribute, but is set to the assembly name.

Create the Package In the same directory as the project file and NuSpec file, run the following command to create a package:

nuget pack ProjectName.csproj

If you have one project file in the same directory, you can omit the project file name when you run the command.

If you haven’t compiled the project yet, you can use the Build flag to compile the project first, before packing it. This will compile the project first before running the pack command:

nuget pack ProjectName.csproj -Build

This command results in a file named ProjectName.{version}.nupkg, where {version} is the same value specified in the AssemblyVersionAttribute. For example, if the version is 1.0.0, your package will be named ProjectName.1.0.0.nupkg. You can use the Package Explorer to examine the package after the fact to ensure it’s been created correctly.

As a courtesy to developers who will install your package, consider using the Symbols flag to create a package with debugger symbols:

nuget pack ProjectName.csproj -Build -Symbols

This command creates a symbols package in addition to the main package. This allows others who install your package to step into the package code when they debug their application.

Publishing a Package

After you create a package, you’ll probably want to share it with the world. NuGet.exe has a publish command for just this purpose. Before you publish, you’ll need to create an account on nuget.org.

When you’ve registered for an account, click on the link to your account to see your access key. This key is important as it identifies the nuget.exe command to the gallery and is a revocable password.

Once you have your key, store it in a secure location using the following command:

nuget setApiKey b688a925-0956-40a0-8327-ff2251cf5f9a

With this in place, use the push command to publish your package to the gallery:

nuget push ProjectName.1.0.0.nupkg

The command validates your API key with the gallery before it uploads the package. If you created a symbols package as we discussed earlier, you should specify the Symbols flag when you push your package:

nuget push ProjectName.1.0.0.nupkg -Symbols

Be sure to specify the main package name and not the symbols package name. The command finds the appropriate symbols package by convention. The command pushes the main package to the NuGet gallery and the symbols package to the partner symbolsource.org repository.

What’s Next

In this article, I demonstrated how NuGet pulls in useful libraries from the NuGet gallery to jump-start new project development. Within enterprises, NuGet is useful for sharing code among various developers in an organization.

But there’s one persistent misperception about NuGet I need to address—that NuGet is only for Web developers. This misperception is probably due to its inclusion with the ASP.NET MVC 3 release, but it’s simply not true. NuGet is not just for Web developers—it’s for all developers. NuGet supports Windows Phone, Silverlight and Windows Presentation Foundation, among other project types, and will support new project types in the future.

NuGet is a community-driven open source project licensed under the Apache 2 license. The project belongs to the Outercurve Foundation but is incorporated into Microsoft products and counts several Microsoft developers as core contributors.

To help in NuGet’s development, visit nuget.codeplex.com to learn about how to get involved and maybe even contribute to NuGet.

This article only scratches the surface of what’s possible with NuGet. To learn more, visit the NuGet documentation Web site at docs.nuget.org (the team works hard to maintain this and accepts contributions to its documentation). The team is active in the CodePlex discussions forum for the NuGet project and welcomes your questions.    


Phil Haack works for Microsoft as a senior program manager on the ASP.NET team aiming to build great products for developers. While he delves into many areas of ASP.NET, his primary projects are ASP.NET MVC and NuGet Package Manager, both released under an OSS license. In his spare time, he writes about software on his blog, haacked.com, and works on the Subtext open source blog engine.

Thanks to the following technical expert for reviewing this article: David Fowler