Thursday, September 28, 2017

Microsoft 70-487: Manage packages by using NuGet

Exam Objectives

Create and configure a NuGet package; install and update an existing NuGet package; connect to a local repository cache for NuGet, set up your own package repository


Quick Overview of Training Materials




NuGet is an open source package management tool for the Microsoft stack.  It was introduced in 2010, and since VS 2012 has come preinstalled.  Many popular tools (Entity Framework, for example) are delivered as NuGet packages.



Manage Installed Package


99% of developers' interactions with NuGet will be in the context of installing libraries into their applications.  The simplest way to add a NuGet package to a project is to right-click on "References" and select "Manage NuGet Packages".  While the interface for the NuGet manager screen has evolved (particularly in VS 2017), it still has the same basic capabilities:  searching for NuGet packages online, viewing and managing the installed packages:

VS 2012 circa 2014

VS 2017 circa yesterday


Once installed, information about what packages your project depends on is stored in a file called packages.config in the root directory of your project.  This is a plain old XML file that has a list of packages with their id, version, and target framework:


<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.Azure.KeyVault.Core" version="1.0.0" targetFramework="net452" />
  <package id="Microsoft.Data.Edm" version="5.7.0" targetFramework="net452" />
  <package id="Microsoft.Data.OData" version="5.7.0" targetFramework="net452" />
  <package id="Microsoft.Data.Services.Client" version="5.7.0" targetFramework="net452" />
  <package id="Newtonsoft.Json" version="8.0.2" targetFramework="net452" />
  <package id="System.Spatial" version="5.7.0" targetFramework="net452" />
  <package id="WindowsAzure.Storage" version="8.0.1" targetFramework="net452" />
</packages>


The libraries themselve are placed in a folder called "packages", also in the root of your project.  By default this folder is included in the Visual Studio generated .gitignore file.  One benefit of having all the package installation in the package.config file is that when the repository is clones, the packages can be restored by NuGet.  Just right click the solution and select "Restore NuGet Packages":



There is also a "Package Manager Console" that provides an interface for installing, removing, updating NuGet packages.  Under Tools => NuGet Package Manager => Package Manager Console. Once it's open, running "get-help nuget" will give you an overview of the available NuGet cmdlets available in the console (detailed info can be found in the PowerShell Reference docs):



So if we wanted to find all the packages related to EntityFramework:

Find-Package -StartsWith entity


Once we have the full name, we can go ahead and install (maybe get a specific version):

Install-Package EntityFramework -Version 4.3.0


If later down the road a new version of EF comes out and we want to upgrade:

Update-Package EntityFramework


If we need to remove a package:

Uninstall-Package EntityFramework



Create and Configure a Package


The physical file that constitutes a "Nuget Package" is essentially a .zip file with a different extention (.nupkg).  Inside this zip file, there is a .nuspec file which is an XML file describing the metadata for the package (id, version, authors, etc.), tags, and dependencies on other NuGet packages and framework assemblies.

There are also folders that serve different purposes:

  • lib - assemblies are added as references, other files are extracted to the global packages folder
  • runtimes - architecture specific assemblies (enables supporting different framework versions)
  • content (or contentFiles) - extracted to the "packages" folder and linked in the project
  • build - .target and .props files for MSBuild
  • tools - PowerShell and other programs accessible from Package Manager Console.  Folder is extracted and added to the PATH env variable.

The NuGet Package Explorer provides a very easy to use GUI interface for manipulating NuGet packages:



On the inside, it's just a .zip file:



NuGet Packages can also be created using the nuget.commandline tool.  I installed this using chocolatey (which I also used to install NuGet Package Explorer since the Windows Store wasn't working for me at all).  There are a couple ways to go about this, but from a high level, it is basically a two step process:  create the .nuspec file, then create the .nupkg file.

Running "nuget spec" will create a template .nuspec file that can be populated with values relevant to the package you are creating.  By default this file is just called Package.nuspec.  If you run this against a .csproj file (which you don't even have to explicitly point at, just run in the root directory of the project), it will create a spec file named after the project (with the version number baked in).

Creating the package file uses the "nuget pack" command.  When run in the root of a Visual Studio project, this will pack up the project itself.  One thing I thought was interesting in this process is that, even though the dependencies didn't materialize when I ran "nuget spec", they were added to the nuspec file when I ran the pack command.  I added EF to this project to illustrate the point:



Alternatively, you can create a document structure that follows the NuGet conventions, and these folders will be included in the created file. 





Connect to Local Repository Cache


The NuGet docs on caching note that NuGet uses several layers of cache, and in newer versions will automatically fall back to these caches when a network connection isn't available. The nuget.commandline tool is able to list these local repos: "nuget locals all -list"



A local filesystem folder can be specified as a package source through Visual Studio. 

Go to "Tools => NuGet Package Manager => Package Manager Settings", and select the "Package Sources" menu.  Below, I've created a local repo that points to the "C:\nuget" folder, which has one package in it (the Dummy package created above):



Now, from the NuGet Package Manager screen in Visual Studio, if I select "My Local Source" as the package source, I'll see the dummy package (and only that package):




Set up a Package Repository


The PluralSight course does a pretty good demo for setting up NuGet.server and NuGet.Gallery (albeit a much older version of Gallery), and the documentation on hosting basically just points to these projects as well as a number of hosting services.  One that I thought was interesting was the TFS Package management functionality, which made me wonder it was available in Visual Studio Team Services... and whad'ya know, it is

To install package management in VSTS, you have to have the appropriate permissions (or be friendly with the people that do).  Once installed, you will need to explicitly add people to the licence for it (I thought this would be automatic).  This is done through the account level user mangement screen (VSTS has a lot of screens, it's confusing...):



Once you have permission, you have to create a feed within a project. This is under the "Build and Release" section... So even though I created this feed from within a project, it is available account-wide (I created another account to demonstrate creating the feed, and *poof* there was the feed I already created... alllllllrighty then).  Add the feed as a source (I did this through Visual Studio, VSTS gives instructions on how to use the cli), then packages can be published to the feed:



Now the dummy package will appear in the VSTS interface:



As of today, sending back the image URL for the icon isn't supported (it's on the backlog), but functionally, this works as expected.

NuGet.Gallery is the technology used by nuget.org, and is a robust option.  It includes the user interface and full featured management functionality.  I think doing a full install of that is a bit out of scope, but once it's set up it operates much the same as the VSTS offering (based on what I saw in the PluralSight course).  NuGet.server is a no-frills option, as it does not include any kind of UI, it just exposes the feed.



No comments:

Post a Comment