How to deal with the NuGet hell of transitive dependencies in your .NET projects

Navigating through the complexity of NuGet package dependencies aka “NuGet hell” in .NET applications can be a daunting task. The project.assets.json file, found in the obj folder of your .NET projects, is a crucial resource in managing these dependencies. This file provides detailed information about the packages used, including direct and transitive dependencies. In this article, we’ll explore what the project.assets.json file is, how to use it to understand your dependencies, and how it can help you keep your packages up to date.

The bad alternatives to project.assets.json file

To make the problem obvious to the reader, let us show some other ways for identifying the structure of the NuGet dependency tree.

The first way would be by opening Manage NuGet packages dialog in Visual Studio. However, in that case you see only a list of the transitive dependencies without knowing which direct dependency uses them:

Find transitive dependencies in the nuget packages dialog in Visual Studio

You could now open the Dependencies\Packages drop-down of your project and try to manually spot the transitive dependency by checking inside all the direct dependencies of your project:

Find transitive dependencies in the Dependencies drop-down in Visual Studio

This is not a good idea… Let us see the proper way to search in the dependency tree of your application.

The project.assets.json file

This file is a JSON document which is generated by the .NET SDK during the build process. It contains a comprehensive list of all NuGet packages that your application depends on, including both direct dependencies (packages explicitly added to your project) and transitive dependencies (packages that are dependencies of your direct dependencies).

The JSON contains the following sections:

Identifying Transitive Dependencies

Transitive dependencies are packages that are required by your direct dependencies. Understanding these can help you troubleshoot issues and ensure compatibility. In the project.assets.json file, you can find transitive dependencies listed under the targets section for each target framework. For example in the following section, the version 18.0.4 of PuppeteerSharp contains three dependencies:

      "PuppeteerSharp/18.0.4": {
        "type": "package",
        "dependencies": {
          "Microsoft.Bcl.AsyncInterfaces": "1.1.0",
          "Microsoft.Extensions.Logging": "2.0.2",
          "Newtonsoft.Json": "13.0.1"
        },
        "compile": {
          "lib/netstandard2.0/PuppeteerSharp.dll": {
            "related": ".xml"
          }
        },
        "runtime": {
          "lib/netstandard2.0/PuppeteerSharp.dll": {
            "related": ".xml"
          }
        }
      }

Updating NuGet Packages

Based on the information gathered in the dependencies sections of the direct dependencies you can identify the current versions of the NuGet packages that used from your direct dependencies and update them to the same version.

Conclusion

The project.assets.json provides a detailed map of all dependencies, including transitive ones and allows you to navigate and manage your project’s package ecosystem effectively. So next time you find yourself in “NuGet hell,” remember that the project.assets.json file is your guide to navigating through it.

comments powered by Disqus