Creating a Nuget Package From a .Net 6 class library
Tags: dotnet, tutorial, showdev, nuget
Published: 2022-11-05 17:10:30

# Backstory...

Recently I was attempting to create a shareable library of code in C# to interact with a new enterprise document storage solution. The document storage solution essentially stored metadata about a document in an onprem database, but stored the document itself in Azure blob storage and kept a reference to the blob in our database. To interact with this service I created an pretty basic web api with just a few endpoints that did some CRUD operations. The api was secured using a client id / client secret provided by our [Okta](https://www.okta.com/) instance.

My main goal with this library, as with all shareable code I write, was to make it as simple as possible to implement the code and interact with the new document storage solution. The code behind this shareable library offered a quick configuration method that setup some services for dependency injection and a factory class that would retrieve those services for the developer, all the while handling authentication in the background so they didn't need to think about it too much. This code had the potential to be used by any group in our organization so simplicity was key as well as access. 

I decided to create a [nuget](https://learn.microsoft.com/en-us/nuget/what-is-nuget) package of the code that we could host in our Azure artifacts nuget feed. If you don't know what a nuget package is, it is essentially a zip file with the .nupkg extension that contains compiled DLL files and any supporting files needed for the shared code.

I've created nuget packages before, but not in quite a while and it seemed like some things had changed since last time. After multiple google searches I was able to piece together something that worked very well to get a nuget package with .net 6, and thought I'd share here... 

# How To...

A couple requirements I had for the package:

1. It needs to be part build pipelines in Azure and get an automated build version.
2. It needs a README file that popups up in Visual Studio with documentation on how to use the code.

So first I created a nuspec file which is essentially a file that defines what needs to be in the package and some metadata about the package itself. It looks like this... 


![nuspec file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1k4sehimesjdw2twds7u.png)

The parts I want you to take notice of are 
```xml
<id>NHA.Document.Client</id>
<version>$version$</version>
...
<readme>README.md</readme>
<dependencies>...</dependencies>
<files>...</files>
```
The id field must be some unique id. If you were to publish this on [https://www.nuget.org/](https://www.nuget.org/) a unique ID is necessary.

The version is dynamic because of the $version$ parameter we will pass to it. More on that in a bit.

Dependencies are any other nuget packages that this code relies on. In this case I use Swashbuckle for some data annotations.

The files section is probably the most important. Here you must list out the files that are necessary for the actual usage of the client library. Any .dll, .pdb files that are compiled for this library must be listed here. Also, if you want to have a readme file popup upon installation you must list it here. The src value is just a file path to where the file exist. Since it is compiled code it will be placed in the bin subdirectory aligning with the .Net version you're on.

_A note on README documentation._
I'm still a little confused on it, but I believe the case is that if you have a readme.txt file it will automatically popup upon installation. With a .txt file you are sort of limited in how nice you can make it look. If you want a nicely formatted markdown readme that displays on the nuget.org site when you publish it then you also need that file in the package and have it referenced in the <readme> tag of the nuspec file.

Once I created the nuspec file and saved it at the root of the client library as NHA.Document.Client.nuspec I was ready for the next step.

The next piece was to modify the .csproj file for the client library I was packaging. It looks like this...

![csproj file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ftfopu34oria0njmpy3x.png)

The main part to take notice of is 
```xml
<PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
	<NuspecFile>NHA.Document.Client.nuspec</NuspecFile>
	<NuspecProperties>version=$(PackageVersion)</NuspecProperties>
</PropertyGroup>
```
This section says where to get the .nuspec file definition for the packaage and sets up our $version$ variable. In our case we are going to get the version from the actual build id and pass it in when we use the [dotnet pack](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-pack) command. More on that in just a sec...

There is another section below... but if I'm honest I don't for sure if it's necessary :) ... I don't remember adding this and I am unsure how it got there... either way here it is.

```xml
<ItemGroup>
    <None Update="README.md">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
      <Pack>True</Pack>
      <PackagePath>\</PackagePath>
    </None>
</ItemGroup>
```
With that we are ready to pack it up with the "dotnet pack" command. We need to point the pack command at the csproj and pass some additional arguments.

```bash
dotnet pack NHA.Document.Client.csproj  -p:PackageVersion=2.0.5 -c Release
```
If I run this command at the root of the client project it will find the csproj file which then points to the nuspec file. Using the -p: command we can pass in variable values. In this case we pass in a version number. The -c command is for the build configuration to use, in this case I use Release. You can run this from the command line if you have dotnet installed or include it in your build yml files. In my case the command in my yml files looks like this...
```bash
--target=pack --build-arg VERSION="$(Build.BuildNumber)"
```

Using this command gets the build number from the build and that becomes our package version. Our build pipeline kicks off automatically every time we PR to the main branch. 

#Conclusion
So there it is... how I build nuget packages from a dotnet 6 class library. Probably not terribly exciting to many, but I know when I was working on it I did a lot of google searching and trial and error some hopefully this helps anyone else trying to do the same thing.