DEV Community

Cover image for How NuGet Works
Loïc Sharma
Loïc Sharma

Posted on

How NuGet Works

Ever wondered how package managers work?

NuGet is the package manager for the .NET ecosystem that has served billions of downloads worldwide. Let's take a look under the hood and see what happens when you install a package on Visual Studio.

Table of contents

Package Source

If you open Visual Studio's options, you'll see the following under the Package Sources section:

Visual Studio package sources

Visual Studio uses this package source to discover and download packages. The default source is nuget.org, which has the following package source URL: https://api.nuget.org/v3/index.json.

If you open that URL in your browser, you'll see:

{
  "version": "3.0.0",
  "resources": [
    {
      "@id": "https://azuresearch-usnc.nuget.org/query",
      "@type": "SearchQueryService",
      "comment": "Query endpoint of NuGet Search service (primary)"
    },
    ...
  ],
  ...
}

This is the service index, which lists all the resources that the server supports. Each resource has the following properties:

  • @type - Used to identify the resource
  • @id - The resource's URL

For example, the search resource used to discover packages has the type SearchQueryService and can be found at the URL https://azuresearch-usnc.nuget.org/query.

⚠ Don't hard-code azuresearch-usnc.nuget.org in your app! NuGet servers can move their resources at any time - you should always discover resource URLs using the service index.

Discover packages

You can use Visual Studio's Package Manager UI to find packages:

Visual Studio's package manager search

This is powered by the source's search resource. If you search for json, this will trigger the following request: https://azuresearch-usnc.nuget.org/query?includePrerelease=true&semVerLevel=2.0.0&q=json.

If you open that URL in your browser, you'll see:

{
  ...
  "totalHits": 3818,
  "data": [
    {
      ...
      "id": "Newtonsoft.Json",
      "version": "12.0.3",
      "description": "Json.NET is a popular high-performance JSON",
      "totalDownloads": 506643420,
      ...
    },
    ...
  ]
}

This is the metadata for the latest version of each package relevant to json.

Inspect package details

Now that you've discovered some packages, you can select one to view more details:

Alt Text

This is powered by the package metadata resource. For example, you can find the package metadata for the package Newtonsoft.Json at this URL: https://api.nuget.org/v3/registration5-gz-semver2/newtonsoft.json/index.json

If you open that URL in your browser, you'll see:

{
  ...
  "items": [
    {
      "items": [
        {
          ...
          "catalogEntry": {
            "id": "Newtonsoft.Json",
            "version": "3.5.8",
            "description": "Json.NET is a popular high-performance JSON framework for .NET",
            "packageContent": "https://api.nuget.org/v3-flatcontainer/newtonsoft.json/3.5.8/newtonsoft.json.3.5.8.nupkg",
            ...
          },
          "packageContent": "https://api.nuget.org/v3-flatcontainer/newtonsoft.json/3.5.8/newtonsoft.json.3.5.8.nupkg",
        },
        ...
      ]
    }
  ],
  ...
}

This resource contains the metadata for all versions of Newtonsoft.Json.

Install packages

If you press the Install button for the package Microsoft.Extension.Logging, this will kick off the following chain reaction:

  1. Download the package
  2. Inspect the package's dependencies
  3. For each dependency, find the best version of that dependency to install and repeat steps 1-3

All of this is powered by the package content resource.

Download the package

NuGet will download the package using this URL: http://api.nuget.org/v3-flatcontainer/microsoft.extensions.logging/3.1.4/microsoft.extensions.logging.3.1.4.nupkg

For each dependency, find the best version to install

A package can depend on other packages, and these dependencies can themselves have their own dependencies. As a result, NuGet needs to build a graph of all the dependencies using its dependency resolution algorithm. To do this, NuGet needs to know the list of versions for each dependency.

For example, the package Microsoft.Extensions.Logging depends on Microsoft.Extensions.Logging.Abstractions, so NuGet will lookup versions here: https://api.nuget.org/v3-flatcontainer/microsoft.extensions.logging.abstractions/index.json.

If you open that in your browser, you'll see:

{
  "versions": [
    "1.0.0-rc1-final",
    "1.0.0-rc2-final",
    ...
    "3.1.4"
  ]
}

These are all the versions of the Microsoft.Extensions.Logging.Abstractions package. NuGet will choose one of these to install.

⚠ The NuGet client could use the package metadata resource from the previous section to find packages' versions. However, performance is critical here! This endpoint returns just the right information to install the right package.

Conclusion

Congratulations, you've learned how the NuGet protocol works! If you want even more information, I recommend the following resources:

If you want to run your own NuGet server, check out my side project on GitHub! 😇

GitHub logo loic-sharma / BaGet

A lightweight NuGet and symbol server

In future posts, I'll deep dive into nuget.org's implementation of the NuGet protocol, so stay tuned! Feel free to comment if you have any feedback or questions!

Top comments (0)