Inside the NuGet Package Manager
The popular, open source Nuget Package Management system makes quick work of installing, configuring and updating third-party components in.NET projects.
Welcome to the new Open Source .NET column at the Visual Studio Magazine Web site. Each month I'll explore the compelling intersection of open source and .NET development, and look at ways developers can improve their efforts by integrating open source tooling and solutions into their workflow.
This month, I look into NuGet, the open source package management system for .NET Framework that is getting a lot of attention in the dev community.
Componentization is the ability to build large applications in parts (or components), and is a key tenant of writing software with .NET. The "components" of a .NET application are assemblies, but frequently an assembly isn't sufficient on its own. The assemblies have additional files, their own assembly dependencies, and even configuration settings that need to accompany their use.
The combination of one or more assemblies, settings, and files is a package. And, although componentization is a key design principal of .NET, managing a project's dependency packages and (possibly) its additional dependency packages can be laborious. These packages can be provided by third parties or by other teams within the organization, which can lead to mistakes or out-of-date dependencies when locating, downloading, referencing, configuring or updating dependencies.
Those using .NET have been missing a vital piece of development tooling: the package management system. A package management system is a collection of tools that handle the installation, configuration, removal and upgrade of external components.
Although NuGet is an open source project in the Outercurve Foundation, it is not just for open source projects. As described on the NuGet home page, "NuGet is a free, open source developer focused package management system for the .NET platform intent on simplifying the process of incorporating third party libraries into a .NET application during development."
NuGet is for any third-party libraries or components that an application depends on. It is a commercially backed, open source project that is supported by Microsoft developers, even as developers in the community are able fork, enhance and submit changes to be included in the software. (The Ruby community has for years had a NuGet equivalent called Gems, and you'll be hard pressed to find a Ruby developer that doesn't love it.)
There are two ways that you can go about installing NuGet. The first way is to go to http://nuget.org and click on the Install NuGet button. This will download a Visual Studio 2010 extension package. Once the download is complete, run the package.
[Click on image for larger view.]
The second method can be done from within Visual Studio. Open the Extension Manager (Tools | Extension Manager...) and select Online Gallery. You can either browse for it on the list as "NuGet Package Manager" or use the search bar in the top right corner and search for NuGet. Once selected, click Download and follow the prompts to install it.
Once you have NuGet installed, you can use the Extension Manager to update NuGet along with any other installed extensions.
With NuGet installed you can work with this extension through either PowerShell commands in the Package Manager Console or the Add Library Package Reference dialog.
In the latter case, right-click on your reference folder and select Add Library Package Reference to invoke NuGet's package management system.
For example, consider creating an ASP.NET MVC3 application with references to Ninject.MVC3 (an IoC container), NLog2 (a logging framework), and Entity Framework 4.1 (for database access). Without NuGet, one would have to browse the Web, find the latest (stable) downloads that match the target environment, and determine external dependencies, download all of the libraries, unblock the zip files, add the references into the projects, and perform configuration. NuGet boils this complexity down to a simple selection process.
From the Add Library Package Reference dialog simply search and select the references needed (see Figure X) before clicking Install.
In the case of referencing Ningect.MVC3, for example, Ninject 2.2 (or later) and WebActivator 1.4 (or later) are also required. NuGet, however, will download the package and its dependencies, add the references to your project, generate a WebActivator bootstrapper template and add it to your solution. You will also see a new file, packages.config, which keeps track of the package references that you have installed on this project.
Select the installed packages item from the left hand side and you will see the packages that NuGet has installed for this solution. When NuGet installs a package, it installs it in a packages folder relative to the solution file in use. For each project, NuGet adds the packages.config that refers to this solution level package cache.
Similar steps enable references to Entity Framework and NLog..
Updating Your Stack
If there was a project that had installed, say, NHibernate 188.8.131.5200, it would also have a series of dependencies. These would include:
- log4net 1.2.10
- Iesi.Collections 1.0.1
- Antlr 184.108.40.206154
- Castle.Core 1.1.0
- Castle.DynamicProxy 2.1.0
But now imagine that time has passed and you would like to upgrade to NHibernate.Castle 220.127.116.1100. You can open up the Add Library Package Reference dialog and search for NHibernate.Castle. When you install the package, you will see a log similar to:
'NHibernate (= 18.104.22.16800)' not installed. Attempting to retrieve dependency from source...
'Castle.Core (≥ 2.5.2)' not installed. Attempting to retrieve dependency from source...
'Iesi.Collections 22.214.171.12400' already installed.
Successfully installed 'NHibernate 126.96.36.19900'.
Successfully installed 'Castle.Core 2.5.2'.
Successfully installed 'NHibernate.Castle 188.8.131.5200'.
Successfully removed 'NHibernate 184.108.40.20600' from NuGetSample.
Successfully uninstalled 'NHibernate 220.127.116.1100'.
Successfully removed 'Castle.DynamicProxy 2.1.0' from NuGetSample.
Successfully uninstalled 'Castle.DynamicProxy 2.1.0'.
Successfully removed 'Castle.Core 1.1.0' from NuGetSample.
Successfully uninstalled 'Castle.Core 1.1.0'.
Successfully removed 'Antlr 18.104.22.168154' from NuGetSample.
Successfully uninstalled 'Antlr 22.214.171.124154'.
Successfully removed 'log4net 1.2.10' from NuGetSample.
Successfully uninstalled 'log4net 1.2.10'.
Successfully added 'NHibernate 126.96.36.19900' to NuGetSample.
Successfully added 'Castle.Core 2.5.2' to NuGetSample.
Successfully added 'NHibernate.Castle 188.8.131.5200' to NuGetSample.
You can see that NuGet is finding which packages you are missing, removing the old packages from your project, and adding the new packages and their dependencies into your solution. In less than a minute, you can update your entire stack with NuGet.
The Package Manager Console
Until now, we have stayed in the Visual Studio 2010 menus. However, NuGet is a series of tools and we really should check out the Package Manager Console (PMC). Open the PMC via Tools | Library Package Manager | Package Manager Console.
Now you have a PowerShell interactive console with which you can interact with NuGet or run your own PowerShell commands. You can find package with Get-Package. If you execute this command alone, it will list off the packages that are available in your package source. If you want to query the official NuGet feed for packages, add the –remote parameter.
There are only a few commands, but you should get to know them. From the NuGet documentation:
Get-Package: Gets the set of packages that are available from the package source. By default, this command returns installed packages.
Install-Package: Installs a package and its dependencies into the project or the solution. For project packages, this installs the package and applies it to a specific project. Files are copied to the project, assembly references added, the app.config or web.config file is updated, etc.
Update-Package: Updates a package and its dependencies. If the new version of the package has new dependencies, the dependency packages are also installed. If the updated version no longer depends on a package and if no other packages depend on it, the dependency package is uninstalled.
Uninstall-Package: Uninstalls a package. If other packages depend on this package, the command will fail unless the -Force option is specified.
Get-Project: Returns a reference to the DTE (Development Tools Environment) for the active or specified project.
Add-BindingRedirect: Examines all assemblies in the output path for a project and adds binding redirects to the application configuration (app.config) file or to the web configuration (web.config) file where required.
NuGet supports standard PowerShell help so you can run Get-Help Get-Package or Get-Help Get-Package –Full for more information. Explore the command reference in the PowerShell help and NuGet Codeplex site.
Although it is relatively new, NuGet is fully functional as a .NET package management system, but it will continue to evolve with time. Other applications are starting to leverage NuGet in exciting ways, such as providing a management system for executables and application packages. Have more ideas? Fork NuGet and let people know. Have a useful component that others could use? Create a NuGet package and add it to the gallery.
To get started, visit http://nuget.org and browse the packages, or take a look at the multitude of blog posts and documentation on the http://nuget.codeplex.com/ site.