12 min read

(For more resources related to this topic, see here.)

Using NuGet with source control

Source control systems are an integral part of software development. As soon as there is more than one person working on the project, it becomes an invaluable tool for sharing source code. Even when we are on the project on our own, there is no better way for tracking versions and source code changes. The question arises: how should we put the installed packages into source control?

The first impulse would be to simply add the packages folder to the repository. Though this will work, it isn’t the best possible approach. Packages can grow quite large and they can be obtained from elsewhere; therefore, we would only “pollute” the repository with redundant files. Many source control systems don’t handle large binary files well. Even for those that don’t have such problems, having packages in the repository doesn’t add much value; it does noticeably increase the repository size, though.

Fortunately, NuGet offers a feature called Package Restore, which can be used to avoid adding packages to source control. Let’s see how it works.

The following sample will use Team Foundation Service (TFS) for source control. If you don’t have an account yet, you can sign up for free at http://tfs.visualstudio.com. You need a Microsoft account for authentication. If you decide to use a different source control system instead, just skip all the steps dealing with TFS, replacing them with equivalent actions in your source control system of choice.

We’ll start by creating a sample project:

  1. Create a new Console Application project in Visual Studio.
  2. Install the Json.NET NuGet package into the project.
  3. Add the following code to the Main method so that the project won’t compile without a valid reference to the Newtonsoft.Json.dll assembly:

    var jsonString = @"{ ""title"": ""NuGet 2 Essentials"", ""authors"":""Damir Arh & Dejan Dakic"", ""publisher"": ""Packt Publishing"" }"; var parsedJson = Newtonsoft.Json.JsonConvert .DeserializeObject(jsonString);

  4. Compile and run the project to make sure the code works.

It’s time to create a source code repository. If you already have a repository, you can skip the following steps. Just make sure you have a repository ready and know how to connect to it before moving on.

You will need Visual Studio 2012 or Visual Studio 2010 with Service Pack 1 and KB2662296 installed to connect to TFS.

  1. In a browser, navigate to https://<accountname>.visualstudio.com/ (replacing <accountname> with the name you used when signing up for TFS).
  2. Click on New team project.
  3. In the CREATE NEW TEAM PROJECT dialog box, enter the project name (for example, PackageRestore) and click on Create project, leaving the rest of the fields unchanged.
  4. Click on Navigate to project once the creation process is complete.
  5. On the project page, click on Open new instance of Visual Studio in the Activities menu on the right to connect Visual Studio to your TFS account.
  6. You can close this Visual Studio instance once the connection is established.

Now we’re ready to add the project to the repository.

  1. Return to Visual Studio, right-click on the solution node in the Solution Explorer window and click on the Add Solution to Source Control… menu item.
  2. Make sure you select Team Foundation Version Control as the source control system if a dialog box pops up and asks you to make a selection.
  3. In the Connect to Team Foundation Server dialog box which opens next, select your TFS account (for example, accountname.visualstudio.com) from the drop-down list and check the created repository in the Team Projects list box.
  4. Click on Connect to move to the next step and confirm the default settings by clicking on OK in the dialog box that follows.

We still need to select the right set of files to add to source control and check them in so that they will be available for others.

  1. Open the Team Explorer window and click on the Source Control Explorer link inside it.
  2. Look in the tree view on the left side of the Source Control Explorer window. You will notice that apart from your project, the packages folder is also included. We need to exclude it since we don’t want to add packages to source control.

  3. Right-click on the packages folder and select Undo Pending Changes… from the context menu. Click on the Undo Changes button in the Undo Pending Changes dialog box that pops up.
  4. Click on the Check In button in the toolbar and click on Check In again in the Pending Changes pane inside the Team Explorer window. Close the confirmation dialog box if it pops up. The packages folder should now be removed from the tree view.
  5. Navigate to https://<accountname>.visualstudio.com/DefaultCollection/<PackageRestore>/_versionControl from your browser to check which files have been successfully checked in. Replace <accountname> and <PackageRestore> with appropriate values as necessary for your case.

Let’s retrieve the code and place it in a different location and see how the packages are going to get restored:

  1. With TFS, a new workspace needs to be created for that purpose in the Manage Workspaces dialog box, which can be accessed by clicking on Workspaces… from the Workspace drop-down list in the Source Control Explorer toolbar.
  2. Click on Add… to add a new workspace. You need to specify both Source Control Folder (solution folder, that is, $/<PackageRestore>/<SolutionName>) and Local Folder where you want to put the files.
  3. After adding the workspace, confirm the next dialog box to get the files from the repository to your selected local folder.
  4. Check the contents of that folder after Visual Studio is done to see that there is no packages folder inside it.
  5. Open the solution from the new folder in Visual Studio and build it. You should notice a NuGet Package Manager dialog box popping up displaying the package restore progress and closing again once it is done. The application should build successfully. You can run it to see that it works as expected.
  6. If you check the contents of the solution folder once again, you will see that the packages folder has been restored with all the required packages inside it.

Automatic Package Restore, which was described earlier has been available only since NuGet 2.7. In earlier versions, only MSBuild-Integrated Package Restore was supported. In case your repository will be accessed by users still using NuGet 2.6 or older, it might be a better idea to use this instead; otherwise, package restore won’t work for them. You can enable it by following these steps (if you do this in NuGet 2.7, the Automatic Package Restore will get disabled):

  1. Right-click on the solution node in the Solution Explorer window and click on the Enable NuGet Package Restore menu item.
  2. Confirm the confirmation dialog box that pops up briefly explaining what is going to happen.
  3. Another dialog box will pop up once the process is complete.
  4. Notice that a .nuget folder containing three files has been added to the solution shown as follows:

When adding a solution configured like this to the source control, don’t forget to include the .nuget folder as well. The packages folder of course still remains outside source control.

If you encounter a repository with MSBuild-Integrated Package Restore, which was enabled with NuGet 2.6 or older, the restoring of packages before build might fail with the following error:

Package restore is disabled by default. To give consent, open the Visual
Studio Options dialog, click on Package Manager node and check 'Allow
NuGet to download missing packages during build.' You can also give
consent by setting the environment variable 'EnableNuGetPackageRestore'
to 'true'.

This happens because the Allow NuGet to download missing packages during build setting was disabled by default in NuGet versions before 2.7. To fix the problem navigate to Tools | Library | Package Manager | Package Manager Settings to open the option dialog box on the right node; then uncheck and recheck the mentioned setting and click on OK to explicitly set it.

A more permanent solution is to either update NuGet.exe in the .nuget folder to the latest version or to switch to Automatic Package Restore instead as described at http://bit.ly/NuGetAutoRestore.

Using NuGet on a build server

Automatic Package Restore only works within Visual Studio. If you try to build such a solution on a build server by using MSBuild only, it will fail if the packages are missing. To solve this problem, you should use the Command-Line Package Restore approach by executing the following command as a separate step before building the solution file:

C:> NuGet.exe restore pathtoSolutionFile.sln

This will restore all of the packages in the solution, making sure that the build won’t fail because of missing packages. Even if the solution is using MSBuild-Integrated Package Restore, this approach will still work because all of the packages will already be available when it is invoked; and this will just silently be skipped.

The exact procedure for adding the extra step will depend on your existing build server configuration. You should either call it from within your build script or add it as an additional step to your build server configuration.

In any case, you need to make sure you have installed NuGet 2.7 on your build server.

The NuGet Package Restore feature can be optimized even more on a build server by defining a common package repository for all solutions. This way each package will be downloaded only once even if it is used in multiple solutions; saving both the download time and the storage space.

To achieve this, save a NuGet.config file with the following content at the root folder containing all your solutions in its subfolders:

<?xml version="1.0" encoding="utf-8"?> <configuration> <config> <add key="repositorypath" value="C:pathtorepository" /> </config> </configuration>

You can even have more control of your repository location and other NuGet settings by taking advantage of the hierarchical or machine-wide NuGet.config file as explained at http://bit.ly/NuGetConfig.

Using Package Manager Console

We have already used Package Manager Console twice to achieve something that couldn’t have been done using the graphical user interface. It’s time to take a closer look at it and the commands that are available.

The Package Manager Console window is accessible by either navigating to Tools | Library Package Manager | Package Manager Console or by navigating to View | Other Windows | Package Manager Console. The most important commands are used to install, update, and uninstall packages on a project. By default, they operate on Default project selected from a drop-down list in the window’s toolbar. The target project name can be specified using the -ProjectName parameter.

To get a list of all commands, type Get-Help NuGet in the console. To get more information about a command, type Get-Help CommandName in the console, replacing CommandName with the actual name of the command. You can also check the online PowerShell command reference at http://bit.ly/NuGetPsRef.

Let’s take a look at few of the examples:

  • To install the latest version of the Newtonsoft.Json package to the default project, type:

    PM> Install-Package Newtonsoft.Json

  • To install Version 5.0.1 of the Newtonsoft.Json package to the default project, type:

    PM> Install-Package Newtonsoft.Json –Version 5.0.1

  • To install the latest version of the Newtonsoft.Json package to the Net40 project, type:

    PM> Install-Package Newtonsoft.Json –ProjectName Net40

  • To update the Newtonsoft.Json package in all projects to its latest version, type:

    PM> Update-Package Newtonsoft.Json

  • To update the Newtonsoft.Json package in all projects to Version 5.0.3 (this will fail for projects with a newer version already installed), type:

    PM> Update-Package Newtonsoft.Json –Version 5.0.3

  • To update the Newtonsoft.Json package in the Net40 project to the latest version, type:

    PM> Update-Package Newtonsoft.Json –ProjectName Net40

  • To update all packages in all projects to the latest available version with the same major and minor version component, type:

    PM> Update-Package –Safe

  • To uninstall the Newtonsoft.Json package from the default project, type:

    PM> Uninstall-Package Newtonsoft.Json

  • To uninstall the Newtonsoft.Json package from the Net40 project, type:

    PM> Uninstall-Package Newtonsoft.Json –ProjectName Net40

  • To list all packages in the online package source matching the Newtonsoft.Json search filter, type:

    PM> Get-Package –ListAvailable –Filter Newtonsoft.Json

  • To list all installed packages having an update in the online package source, type:

    PM> Get-Package –Updates

    Installed packages can add their own commands. An example of such a package is EntityFramework. To get a list of all commands for a package, type Get-Help PackageName, replacing PackageName with the actual name of the package after it is installed, for example:

    PM> Get-Help EntityFramework

Summary

This article has covered various NuGet features in detail. We started out with package versioning support and the package update process. We then moved on to built-in support for different target platforms. A large part of the article was dedicated to the usage of NuGet in conjunction with source control systems. We have seen how to avoid adding packages to source control and still have them automatically restored when they are required during build. We concluded the article with a quick overview of the console and the commands that give access to features not available using the graphical user interface.

This concludes our tour of NuGet from the package consumer point of view. In the following article, we will take on the role of a package creator and look at the basics of creating and publishing our own NuGet package.

Resources for Article:


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here