Skip to main content
  1. Posts/

Create a NuGet package

·1161 words·6 mins

Whether you are working alone or in a company, duplicating code is never a good practice. It is one of the first rules in computer science: when you create something, you reuse it, consolidate it, but avoid recreating it, except in rare cases.

Our goal here is to create reusable libraries that can be easily integrated into any project or other library.

We will not address the issue of code obfuscation here. Every NuGet package we create, containing DLLs, will potentially be readable by anyone. We will discuss code obfuscation in another article.

To simplify, we will see how to create a NuGet library from C# code and publish it on GitHub.

This will allow you to integrate your libraries very easily using NuGet, just as you already do for any open-source library used in your various projects.

Code Breakdown #

Before diving into the heart of the matter, let’s take a little detour. Creating a NuGet package involves creating a library. This library will contain code, code that will evolve and might also have its own dependencies.

I strongly encourage you to structure your code well, following the standard separation found in .NET: an abstraction library and an implementation library, such as:

  • MyLib.Abstractions
  • MyLib

The abstraction library will contain all the interfaces necessary for the proper functioning of your implementation library, but without knowing the details. This implementation will be reserved for the second library. Don’t worry, we will see right after a method to publish one or more libraries without any problem.

To illustrate this point, here is a diagram representing an example of a library divided into several sub-libraries, thus respecting the separation of roles (SOLID principle), notably the separation of interfaces and implementations:

Example of library separation
Example of library separation

Let’s now take an example of a library you must know: Microsoft.Extensions.Logging. There are several of them, each having their role and notably, in our example, Microsoft.Extensions.Logging.Abstractions. We can clearly see the interfaces separated from the implementations:

Example of library separation with MS Logging
Example of library separation with MS Logging

We can see here that the implementations Logger and LoggerFactory of the library Microsoft.Extensions.Logging respectively inherit from ILogger and ILoggerFactory of another library Microsoft.Extensions.Logging.Abstractions.

Of course, the library Microsoft.Extensions.Logging references Microsoft.Extensions.Logging.Abstractions as a dependency in this case. It will be the same for our own libraries.

Creating NuGet Packages #

Creating NuGet packages is relatively simple. Thanks to the .NET CLI, you can generate all your NuGet packages locally or on your CI very easily.

As you will understand, most of the necessary instructions will not be done directly in the code. They will be executed via the terminal or console with .NET commands.

For more practicality and scalability (local use and on a CI), I suggest using a batch script allowing the automatic execution of NuGet package generation:

while getopts v:k: flag
do
    case "${flag}" in
        v) version=${OPTARG};;
        k) key=${OPTARG};;
    esac
done

dotnet pack "MyLib.csproj" --configuration Release
dotnet pack "MyLib.Abstractions.csproj" --configuration Release

This script is relatively simple:

  • It retrieves the version and key to use as input parameters (we do not want to hardcode the key for security reasons)
  • It uses the dotnet pack command for each library

You can now find your nupkg file in each “bin/Release” folder of each of your libraries.

Publishing on GitHub #

Remember that it is quite possible to use your NuGet packages locally. You do not need to publish them on a server (GitHub or others) if you are working alone or in a small team that does not wish to invest in a server.

However, in this guide, we will see how to share our libraries privately within our organization, so that everyone working with us can use them.

Fortunately for us, GitHub offers all the necessary features for this.

To start, go to your GitHub account settings. Then go to “Developer settings”, then “Personal access tokens” and finally “Tokens (classic)”.

Github personal access tokens
Github personal access tokens

We will now create a new token. It will need at least the following permissions:

  • delete:packages
  • repo
  • write:packages

For obvious security reasons, it is strongly recommended to create tokens with the least possible permissions.

As you will understand, it is necessary to save the new key generated. If you don’t want to have problems later: unable to publish, someone else published in your place, etc…

I emphasize an obvious point: never share your access key with anyone, even within your organization. Each user must have their own key.

We will now modify the previous script to manage automatic publishing on GitHub:

dotnet nuget push "MyLib/bin/Release/MyLib.$version.nupkg" --api-key $key --source "myNuget"
dotnet nuget push "MyLib.Abstractions/bin/Release/MyLib.Abstractions.$version.nupkg" --api-key $key --source "myNuget"

The dotnet nuget push command allows this publication. Note that we use the –source parameter with this command. It allows defining the deployment target. In this case, it is our GitHub server.

But before running our script again, it is important to explain to NuGet what myNuget represents. To do this, add the nuget.config file to the root of your project:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <packageSources>
        <clear />
        <add key="myNuget" value="https://nuget.pkg.github.com/MyTeam/index.json" />
    </packageSources>
    <packageSourceCredentials>
        <github>
            <add key="Username" value="MyUsername" />
        </github>
    </packageSourceCredentials>
</configuration>
The URL of your NuGet repository is always “https://nuget.pkg.github.com” suffixed with your organization name and /index.json.

You can now run the script again and see your library directly on your GitHub account!

So now how to use them?

Using a Custom Library via NuGet #

For those unfamiliar with NuGet, it works similarly to Maven and other well-known dependency managers on various platforms. In other words, there are main servers managed by large companies and automatically used by different development environments (IDEs). However, it is quite possible to add our own sources and configure our own NuGet servers.

We will therefore add a new data source to our IDE. Here are configuration examples for the two main IDEs.

With Visual Studio #

With Visual Studio it’s very simple. Go to the “Options” > “NuGet Package Manager” settings and click on “+”

Visual Studio settings
Visual Studio settings

From there, you just need to enter the required information and you’re done! In the NuGet package manager, you will see your new source:

NuGet Package Manager
NuGet Package Manager

With Rider #

When you open your NuGet dependencies manager in Rider, go to the “Sources” tab. It will offer you a default list of available configurations:

  • [Effective NuGet.Config]
  • And your own configuration

It is in the latter that we will add a new source. Select it and click on the “+” button.

Add a NuGet source
Add a NuGet source
In some cases, the source is not enabled by default, don’t forget to check the “Enable” box to use it.

You can now directly see your libraries in your NuGet manager:

Libraries in the NuGet manager
Libraries in the NuGet manager

In conclusion, creating and sharing NuGet packages can greatly facilitate dependency management and code reusability, whether you are working alone or in a team. By following these steps and adopting good practices, you can optimize your workflows and improve collaboration within your organization.

Hoping you enjoyed this article, feel free to share it and come!