Exploring the NuGet client libraries

  • Gérald Barré

We often use NuGet through Visual Studio or dotnet CLI, but you can also use the same using your own application. In this post, I'm going to show multiple examples of using the .NET client library for NuGet.

To start using the NuGet client library, you need to add a reference to the NuGet packages:

  <ItemGroup>
    <PackageReference Include="NuGet.Protocol" Version="5.10.0" />
    <PackageReference Include="NuGet.LibraryModel" Version="5.10.0" />
    <PackageReference Include="NuGet.Commands" Version="5.10.0" />
  </ItemGroup>

#Reading user settings

// Load machine and user settings
var settings = Settings.LoadDefaultSettings(null);

// Extract some data from the settings
string globalPackagesFolder = SettingsUtility.GetGlobalPackagesFolder(settings);
var sources = SettingsUtility.GetEnabledSources(settings);

#Searching packages

var repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
var resource = await repository.GetResourceAsync<PackageSearchResource>();
var searchFilter = new SearchFilter(includePrerelease: false)
{
    IncludeDelisted = false,
    SupportedFrameworks = new[] { FrameworkConstants.CommonFrameworks.Net50.Framework },
};

var results = await resource.SearchAsync(
    "Meziantou.Framework",
    searchFilter,
    skip: 0,
    take: 10,
    NullLogger.Instance,
    CancellationToken.None);

foreach (IPackageSearchMetadata result in results)
{
    Console.WriteLine($"{result.Identity.Id}@{result.Identity.Version}");
}

#Listing package versions

var cache = new SourceCacheContext();
var repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");

var resource = await repository.GetResourceAsync<FindPackageByIdResource>();
var versions = await resource.GetAllVersionsAsync(
    "Meziantou.Framework",
    cache,
    NullLogger.Instance,
    CancellationToken.None);

Console.WriteLine(versions.FindBestMatch(VersionRange.Parse("3.0.*"), version => version));

#Downloading a package

var cache = new SourceCacheContext();
var repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
var resource = await repository.GetResourceAsync<FindPackageByIdResource>();

using MemoryStream packageStream = new MemoryStream();
await resource.CopyNupkgToStreamAsync(
    "Meziantou.Framework",
    new NuGetVersion("3.0.15"),
    packageStream,
    cache,
    NullLogger.Instance,
    CancellationToken.None);

#Extracting package metadata

// packageStream comes from the previous example
using var packageReader = new PackageArchiveReader(packageStream);
var nuspecReader = await packageReader.GetNuspecReaderAsync(cancellationToken);

_ = nuspecReader.GetDescription();
_ = nuspecReader.GetLicenseMetadata().License;

// List dependencies
foreach (var dependencyGroup in nuspecReader.GetDependencyGroups())
{
    _ = dependencyGroup.TargetFramework;
    _ = dependencyGroup.Packages;
}

#Checking package compatibility

// true: a netstandard2.0 library is compatible with net5.0 project
DefaultCompatibilityProvider.Instance.IsCompatible(
    NuGetFramework.Parse("net5.0"),
    NuGetFramework.Parse("netstandard2.0"));

// false: a net5.0 library is not compatible with netstandard2.0 project
DefaultCompatibilityProvider.Instance.IsCompatible(
    NuGetFramework.Parse("netstandard2.0"),
    NuGetFramework.Parse("net5.0"));

#Installing package to the global packages folder

ILogger logger = NullLogger.Instance;
CancellationToken cancellationToken = CancellationToken.None;

var settings = Settings.LoadDefaultSettings(null);
var globalPackagesFolder = SettingsUtility.GetGlobalPackagesFolder(settings);
var source = "https://api.nuget.org/v3/index.json";

var cache = new SourceCacheContext();
var repository = Repository.Factory.GetCoreV3(source);
var resource = await repository.GetResourceAsync<FindPackageByIdResource>();

var packageId = "Meziantou.Framework";
NuGetVersion version = new NuGetVersion("3.0.15");

// Download the package
using MemoryStream packageStream = new MemoryStream();
await resource.CopyNupkgToStreamAsync(
    packageId,
    version,
    packageStream,
    cache,
    logger,
    cancellationToken);

packageStream.Seek(0, SeekOrigin.Begin);

// Add it to the global package folder
var downloadResult = await GlobalPackagesFolderUtility.AddPackageAsync(
    source,
    new PackageIdentity(packageId, version),
    packageStream,
    globalPackagesFolder,
    parentId: Guid.Empty,
    ClientPolicyContext.GetClientPolicy(settings, logger),
    logger,
    cancellationToken);

#Retreiving package from the global packages folder

var settings = Settings.LoadDefaultSettings(null);
var globalPackagesFolder = SettingsUtility.GetGlobalPackagesFolder(settings);

var packageId = "Meziantou.Framework";
NuGetVersion version = new NuGetVersion("3.0.15");
var package = GlobalPackagesFolderUtility.GetPackage(new PackageIdentity(packageId, version), globalPackagesFolder);
if (package != null)
{
    _ = package.PackageReader.NuspecReader;
    _ = package.PackageReader.GetSupportedFrameworks();
}

#List packages from nuget.org

private static async Task DownloadCatalog()
{
    var packagesPublishedAfter = DateTime.UtcNow.AddHours(-1);

    var sourceRepository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
    var serviceIndex = await sourceRepository.GetResourceAsync<ServiceIndexResourceV3>();
    var catalogIndexUrl = serviceIndex.GetServiceEntryUri("Catalog/3.0.0");

    using var httpClient = new HttpClient();
    var index = await httpClient.GetFromJsonAsync<CatalogIndex>(catalogIndexUrl);
    var pageItems = index.Items.Where(x => x.CommitTimeStamp > packagesPublishedAfter);

    var leaves = new List<CatalogLeaf>();
    foreach (var pageItem in pageItems)
    {
        var page = await httpClient.GetFromJsonAsync<CatalogPage>(pageItem.Url);
        leaves.AddRange(page.Items.Where(x => x.CommitTimeStamp > packagesPublishedAfter));
    }

    foreach (var leaf in leaves.OrderBy(x => x.CommitTimeStamp))
    {
        Console.WriteLine($"{leaf.Id}@{leaf.Version}");

        // Get the full data about the leaf item
        var str = await httpClient.GetStringAsync(leaf.Url);
    }
}

public abstract class CatalogEntity
{
    [JsonPropertyName("@id")]
    public string Url { get; set; }

    [JsonPropertyName("commitTimeStamp")]
    public DateTime CommitTimeStamp { get; set; }
}

public sealed class CatalogIndex : CatalogEntity
{
    [JsonPropertyName("items")]
    public List<CatalogPage> Items { get; set; }
}

public sealed class CatalogPage : CatalogEntity
{
    [JsonPropertyName("items")]
    public List<CatalogLeaf> Items { get; set; }
}

public sealed class CatalogLeaf : CatalogEntity
{
    [JsonPropertyName("nuget:id")]
    public string Id { get; set; }

    [JsonPropertyName("nuget:version")]
    public string Version { get; set; }

    [JsonPropertyName("@type")]
    public string Type { get; set; }
}

#Additional resources

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee