Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save evillegas92/b10bbb8b5ed9657579e6c2d13609e261 to your computer and use it in GitHub Desktop.
Save evillegas92/b10bbb8b5ed9657579e6c2d13609e261 to your computer and use it in GitHub Desktop.

Upload NuGet Package (.nupkg) to NuGet Feed with NuGet API v3 in C#

If you want to upload a NuGet package you downloaded, or maybe one you created yourself, to your company's NuGet feed, but that feed uses NuGet 3 instead of NuGet 2; fear no more. I will show you how to push that package to NuGet 3 feed in your app.

So in NuGet version 2, all you needed was to use the Nuget.Core package in your app, and with a few lines of code you could upload you're package to any version 2 feed. That is no longer the case in NuGet v3.

Below you will find a utility class that can download a NuGet package (given its id) and upload a NuGet package (given the .nupkg file) to NuGet v3 feed, using NuGet API v3:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NuGet.Common;
using NuGet.Configuration;
using NuGet.Packaging.Core;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;

namespace NuGetPackageSigner.Helpers
{
	internal static class NuGetHelper
	{
		public async static Task<string> DownloadPackage(string nugetRepositoryUrl, string packageId, string downloadDirectory)
		{
			string downloadedNugetPackageFilePath;

			List<Lazy<INuGetResourceProvider>> providers = new List<Lazy<INuGetResourceProvider>>();
			providers.AddRange(Repository.Provider.GetCoreV3());
			PackageSource packageSource = new PackageSource(nugetRepositoryUrl);
			SourceRepository sourceRepository = new SourceRepository(packageSource, providers);

			using (var sourceCacheContext = new SourceCacheContext())
			{
				var findResource = await sourceRepository.GetResourceAsync<FindPackageByIdResource>(CancellationToken.None);
				IEnumerable<NuGetVersion> versions = 
					await findResource.GetAllVersionsAsync(packageId, sourceCacheContext, NullLogger.Instance, CancellationToken.None);
				if (!versions.Any())
					throw new Exception($"Cannot locate package id {packageId} in repository {nugetRepositoryUrl}.");

				PackageIdentity newestPackageIdentity = new PackageIdentity(packageId, versions.Where(version => version.IsLegacyVersion == false).Max());

				string completePackageName = newestPackageIdentity.Id + "." + newestPackageIdentity.Version.ToString();
				string packageDownloadFilePath = Path.Combine(downloadDirectory, completePackageName);

				var packageDownloadContext = new PackageDownloadContext(sourceCacheContext, packageDownloadFilePath, true);
				using (DownloadResourceResult downloadResult = await NuGet.PackageManagement.PackageDownloader.GetDownloadResourceResultAsync(
					new List<SourceRepository> { sourceRepository }, newestPackageIdentity, packageDownloadContext, "",
					NullLogger.Instance, CancellationToken.None))
				{
					if (downloadResult.Status == DownloadResourceResultStatus.NotFound)
						throw new Exception($".nupkg file not found for package {packageId} in repository {nugetRepositoryUrl}.");
					if (downloadResult.Status == DownloadResourceResultStatus.Cancelled)
						throw new Exception($"Download of .nupkg file was cancelled for package {packageId}. Please try again.");
					if (downloadResult.Status == DownloadResourceResultStatus.AvailableWithoutStream)
						throw new Exception($"Error retrieving stream of the downloaded .nupkg file for package {packageId}. Please try again.");

					downloadedNugetPackageFilePath = Path.Combine(packageDownloadFilePath, completePackageName + ".nupkg");
					using (FileStream fileStream = File.Create(downloadedNugetPackageFilePath, (int)downloadResult.PackageStream.Length))
					{
						byte[] bytesInStream = new byte[downloadResult.PackageStream.Length];
						downloadResult.PackageStream.Read(bytesInStream, 0, (int)downloadResult.PackageStream.Length);
						fileStream.Write(bytesInStream, 0, (int)downloadResult.PackageStream.Length);
					}						
				}				
			}

			return downloadedNugetPackageFilePath;
		}

		public async static Task UploadPackage(string nugetRepositoryUrl, string packagePath, string apiKey)
		{
			List<Lazy<INuGetResourceProvider>> providers = new List<Lazy<INuGetResourceProvider>>();
			providers.AddRange(Repository.Provider.GetCoreV3());
			PackageSource packageSource = new PackageSource(nugetRepositoryUrl);
			SourceRepository sourceRepository = new SourceRepository(packageSource, providers);

			using (var sourceCacheContext = new SourceCacheContext())
			{
				PackageUpdateResource uploadResource = await sourceRepository.GetResourceAsync<PackageUpdateResource>();
				await uploadResource.Push(packagePath, null, 480, false, (param) => apiKey, null, NullLogger.Instance);
			}
		}
	}
}

Hope this helps someone, as there is not much documentation on the subject.

@rsangeethk
Copy link

SAVIOUR!!! 🙇‍♂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment