Saturday, February 9, 2013

Using Nuget Packages in an Enterprise Software

Nuget has become the technology standard to include the dependencies of a project. These dependencies can simply be assemblies referenced in order to use a particular framework. We can also create our own nuget packages and make it available in the nuget repository. The packages can be installed using Nuget Package Manager which would download the packages from the repository. When we include a Nuget package, the assemblies are referenced from the "packages" folder in the solution directory. This can simply be understood as the same "Lib" folder we used to have in our projects to include common libraries which are then referenced by all the projects in a solution, except nuget packages can be a lot more than a bunch of assemblies.

In an organizational setup, the source code is maintained under a source control where it is shared between all the developers. If the organization has embraced continuous integration, there must be a build server which would keep the project working based on certain events [code check-ins, periodic intervals etc]. We might not want to check-in the "packages" folder to the source control and other developers and build server to automatically get it from the source. But we would not want other developers to get it directly from the repository as there are great chances that they might select a wrong version of the package. Then you could end-up in a situation like "It's working on my machine" which would later be identified as "Oops, wrong package version". We just want to avoid this situation. So there must be some way so that other developers and build server automatically install the packages as specified in "packages.config" and they don't have to reference the projects themselves. This is exactly the topic of our discussion today.

We will be using Visual Studio 2012 Ultimate for our example.

Automatic Package Restore Configuration
Visual Studio 2012 supports automatic download of referenced Nuget apps if they are missing from packages folder. Let's create a WPF project in Visual Studio 2012 and name it AutoNugetApp.

First we need to allow Visual Studio to automatically download Nuget packages. This setting is configured in Tools -> Options. Please select PackageManager -> General Tab. You will notice the following setting:

Just enable that. The same config page also supports clearing and browsing Nuget Cache [to be discussed later in this post]. You can also clear recent packages list. This is available when you are adding packages to your projects so that you don't have to search them each time. Now Visual Studio is all setup to download missing packages from Package Source. We also need to support restoration of packages on solution level. Just right click the solution in Solution Explorer and select Enable Package Restore.

This should add a solution folder .nuget. This also contains a build target file. The related nuget configuration is provided in nuget.config file. For our solution, you can only find disableSourceControlIntegration setting. This enables / disables the addition of packages folder to source control. You can find other related configuration here []. We can even change the packages downloaded into some folder other than packages folder.

Let's add MVVMLight package to our WPF application. This would add packages.config file with the details about the added packages.

Now let us build the project and notice the packages folder in the solution folder.

You can also notice the build file to the project configuration. Just unload the project and see the project configuration by selecting Edit Project in solution explorer.

Let's delete the packages folder and build the project again. This should still build. You can notice that it has created the packages folder again for the packages added. Let's call it a success.

Manual Package Restore Configuration:
Let's see how we can do it manually without any package related support from visual studio. Let's create a sample WPF project. Since we have heard that [MVVM is cool], let's base our design on it. We add MVVM Light Package to the solution as follows:

This should add packages.config to our project as follows:

Additionally, this should add a packages folder to the project directory. This folder contains the assemblies and other related files added by package provider.

Now let us build the project. It should be building successfully. Now we need to see how we can enable automatic restoration of packages. Let us delete packages folder from the solution directory. This should cause the build to fail as the referenced assemblies are not available. We need a mechanism for the automatic download of the assemblies from the package source. When we build the project, you should see the following:

Let us get create a folder named Nuget in the solution directory, and add nuget.exe from AutoNugetApp. You can also get it from codeplex.

In order to avoid build failures we need to download the packages referenced before build. We can define a pre-build event to install the package. The install package command downloads the packages in the packages folder in solution directory.

You might have noticed double quotes. They are just to accommodate any specified in the path. Just open the Property window for the project and update the pre-build event as above. This should look like this:

That's it. Now we can build the project. The pre-build event would cause the installation of the packages as specified in Packages.config file for the project. Since all the assemblies are available in the "packages" folder, as expected by the project, it should build fine now.

[Note]: Now when the other developers and build server would get the code from the source control, the [packages]folder would be missing. As they start building the project, Nuget.exe would install the necessary packages which would then be used by the project build. You do need to check-in the Nuget directory created under the solution folder. []

Nuget Cache
Nuget also supports an offline cache for faster access to the missing nuget packages required for a project. This cache is maintained in AppData folder. For our solution we are using MVVM Light package. The package can be found as follows:

In case of non-availability of network, this can be really useful. We can even use this as a Nuget Package source for the other projects. Or we can just update their packages.config and this can be automatically used as they would be found missing. If we need to verify if it is really using the packages from the cache, just delete "Packages" folder and get your machine off the network. With the current configuration, the packages are used from cache. We can hookup Process Monitor to verify this.

Creating Nuget Package
The easiest way to create nuget packages is to use a tool. Nuget packages can be created using Nuget Package Explorer. The tool is available on CodePlex []

Let's create a sample package using libraries from our CoffeeHouseApp. We are adding libraries for portable models and view models. This also contains a config file. For the sample package, it is just an empty file but you might support some configuration which could help better use the libraries in your package.

Remember we have just seen the nuget download cache. The explorer supports viewing the cache. It also supports clearing the contents so that the packages are downloaded directly from the source. Selecting View Nuget Cache would open the same cache from the AppData folder.

Package Visualizer
Package Visualizer is an amazing tool to view the packages referenced by all the projects in a solution. You can just select [Tools -> Library Package Manager -> Package Visualizer] to open the use this. This should open a dgml file with the details of your projects and their referenced packages. If two or more projects reference the same package, it would be displayed as a single node with references shown from all such projects. Let's add another console application project. We are referencing nunit package to both projects.

It also lets you visualize the dependencies of a package on other packages. Here you can see the dependencies of nuget.server package after installing it to your project.


No comments: