What is NuGet? Complete Guide to .NET Package Management
NuGet is the package manager for .NET that allows you to share and consume useful code libraries. With over 400,000 packages available, NuGet is essential for modern .NET development. This comprehensive guide covers everything you need to know about NuGet package management.
What is NuGet?
NuGet is a package management system designed specifically for the Microsoft .NET ecosystem. It provides:
- Package Distribution: Share libraries and tools
- Dependency Management: Automatically resolve and install dependencies
- Versioning: Semantic versioning for compatibility
- Package Discovery: Search and browse available packages
- Private Feeds: Host internal packages securely
NuGet Ecosystem Components
┌─────────────────────────────────────────┐
│ Your Project │
├─────────────────────────────────────────┤
│ NuGet Packages │
├─────────────────────────────────────────┤
│ Package Sources │ ← NuGet.org, Private feeds
├─────────────────────────────────────────┤
│ NuGet Client │ ← CLI, Visual Studio, etc.
└─────────────────────────────────────────┘
Understanding NuGet Packages
What is a Package?
A NuGet package is a single ZIP file with the .nupkg
extension that contains:
- Compiled Code: DLLs and executables
- Metadata: Package information and dependencies
- Content Files: Configuration files, documentation
- Build Scripts: MSBuild targets and props files
Package Structure
MyPackage.1.2.3.nupkg
├── lib/
│ ├── net6.0/
│ │ └── MyLibrary.dll
│ └── netstandard2.0/
│ └── MyLibrary.dll
├── content/
│ └── config.json
├── build/
│ └── MyPackage.targets
└── MyPackage.nuspec
Installing and Managing Packages
Using Visual Studio
-
Package Manager UI:
- Right-click project → Manage NuGet Packages
- Browse, install, update, and uninstall packages
- View package details and dependencies
-
Package Manager Console:
# Install package
Install-Package Newtonsoft.Json
# Install specific version
Install-Package Newtonsoft.Json -Version 13.0.3
# Update package
Update-Package Newtonsoft.Json
# Uninstall package
Uninstall-Package Newtonsoft.Json
Using .NET CLI
# Install package (latest version)
dotnet add package Newtonsoft.Json
# Install specific version
dotnet add package Newtonsoft.Json --version 13.0.3
# Install prerelease package
dotnet add package Microsoft.Extensions.Hosting --prerelease
# List installed packages
dotnet list package
# Remove package
dotnet remove package Newtonsoft.Json
# Restore packages
dotnet restore
Package Reference Format
Modern .NET projects use PackageReference
format in project files:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
</ItemGroup>
</Project>
Popular NuGet Packages
Essential Packages for Every Developer
# JSON serialization
dotnet add package Newtonsoft.Json
dotnet add package System.Text.Json # Built-in with .NET Core+
# Logging
dotnet add package Serilog.AspNetCore
dotnet add package Microsoft.Extensions.Logging
# HTTP client
dotnet add package Microsoft.Extensions.Http
# Configuration
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.Json
# Dependency injection
dotnet add package Microsoft.Extensions.DependencyInjection
dotnet add package Microsoft.Extensions.Hosting
Web Development Packages
# ASP.NET Core
dotnet add package Microsoft.AspNetCore.App # Meta-package
# Entity Framework
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
# Authentication & Authorization
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
# API Documentation
dotnet add package Swashbuckle.AspNetCore
# Validation
dotnet add package FluentValidation.AspNetCore
Testing Packages
# Unit testing frameworks
dotnet add package xunit
dotnet add package xunit.runner.visualstudio
dotnet add package Microsoft.NET.Test.Sdk
# Mocking
dotnet add package Moq
dotnet add package NSubstitute
# Assertion libraries
dotnet add package FluentAssertions
dotnet add package Shouldly
# Test data generation
dotnet add package Bogus
dotnet add package AutoFixture
Utility Packages
# Object mapping
dotnet add package AutoMapper
dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection
# Caching
dotnet add package Microsoft.Extensions.Caching.Memory
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis
# Background tasks
dotnet add package Hangfire.AspNetCore
dotnet add package Quartz.Extensions.Hosting
# Date/time handling
dotnet add package NodaTime
# Rich command-line apps
dotnet add package System.CommandLine
dotnet add package Spectre.Console
Package Versioning
Semantic Versioning (SemVer)
NuGet follows Semantic Versioning: MAJOR.MINOR.PATCH[-PRERELEASE]
- MAJOR: Breaking changes
- MINOR: New features (backward compatible)
- PATCH: Bug fixes (backward compatible)
- PRERELEASE: Alpha, beta, rc versions
Version Constraints
<!-- Exact version -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<!-- Minimum version -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.0" />
<!-- Version range -->
<PackageReference Include="Newtonsoft.Json" Version="[13.0.0,14.0.0)" />
<!-- Floating version (not recommended for production) -->
<PackageReference Include="Newtonsoft.Json" Version="13.*" />
<!-- Prerelease versions -->
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0-rc.1" />
Version Range Syntax
Notation | Description | Example |
---|---|---|
1.0 | Minimum version | ≥ 1.0 |
(1.0,) | Exclusive minimum | > 1.0 |
[1.0] | Exact version | = 1.0 |
(,1.0] | Maximum inclusive | ≤ 1.0 |
(,1.0) | Maximum exclusive | < 1.0 |
[1.0,2.0] | Range inclusive | ≥ 1.0 and ≤ 2.0 |
(1.0,2.0) | Range exclusive | > 1.0 and < 2.0 |
Dependency Management
Understanding Dependencies
When you install a package, NuGet automatically resolves and installs its dependencies:
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
<!-- This automatically brings in: -->
<!-- Microsoft.EntityFrameworkCore.Relational -->
<!-- Microsoft.EntityFrameworkCore -->
<!-- Microsoft.Extensions.DependencyInjection -->
<!-- System.Data.SqlClient -->
Viewing Dependencies
# List all packages including transitive dependencies
dotnet list package --include-transitive
# Check for outdated packages
dotnet list package --outdated
# Check for vulnerable packages
dotnet list package --vulnerable
# See dependency tree
dotnet list package --include-transitive --format json
Dependency Conflicts
When multiple packages require different versions of the same dependency:
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<!-- These packages might have conflicting dependencies -->
<PackageReference Include="PackageA" Version="1.0.0" />
<PackageReference Include="PackageB" Version="2.0.0" />
<!-- Force specific version to resolve conflicts -->
<PackageReference Include="ConflictingDependency" Version="3.0.0" />
</ItemGroup>
</Project>
Package Sources and Feeds
Default Package Source
By default, NuGet uses the official NuGet Gallery:
# List configured sources
dotnet nuget list source
# Default output:
# Registered Sources:
# 1. nuget.org [Enabled]
# https://api.nuget.org/v3/index.json
Adding Package Sources
# Add private package source
dotnet nuget add source https://my-company.pkgs.visualstudio.com/_packaging/MyFeed/nuget/v3/index.json --name MyCompanyFeed
# Add source with authentication
dotnet nuget add source https://my-private-feed.com/nuget --name PrivateFeed --username myuser --password mypass
# Add local folder as source
dotnet nuget add source C:\LocalPackages --name LocalPackages
NuGet Configuration
Configure sources in nuget.config
:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="MyCompanyFeed" value="https://my-company.pkgs.visualstudio.com/_packaging/MyFeed/nuget/v3/index.json" />
</packageSources>
<packageSourceCredentials>
<MyCompanyFeed>
<add key="Username" value="myuser" />
<add key="ClearTextPassword" value="mypass" />
</MyCompanyFeed>
</packageSourceCredentials>
</configuration>
Creating Your Own NuGet Packages
Simple Library Package
- Create a Class Library:
dotnet new classlib -n MyAwesomeLibrary
cd MyAwesomeLibrary
- Update Project File:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>MyAwesome.Library</PackageId>
<Version>1.0.0</Version>
<Authors>Your Name</Authors>
<Company>Your Company</Company>
<Description>An awesome library that does amazing things</Description>
<PackageTags>utility;helper;awesome</PackageTags>
<PackageProjectUrl>https://github.com/yourusername/myawesome-library</PackageProjectUrl>
<RepositoryUrl>https://github.com/yourusername/myawesome-library</RepositoryUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>
</Project>
- Write Your Library Code:
namespace MyAwesome.Library
{
public static class StringExtensions
{
/// <summary>
/// Reverses the characters in a string
/// </summary>
/// <param name="input">The string to reverse</param>
/// <returns>The reversed string</returns>
public static string Reverse(this string input)
{
if (string.IsNullOrEmpty(input))
return input;
char[] chars = input.ToCharArray();
Array.Reverse(chars);
return new string(chars);
}
/// <summary>
/// Checks if a string is a palindrome
/// </summary>
/// <param name="input">The string to check</param>
/// <returns>True if the string is a palindrome</returns>
public static bool IsPalindrome(this string input)
{
if (string.IsNullOrEmpty(input))
return true;
string cleaned = input.ToLowerInvariant().Replace(" ", "");
return cleaned == cleaned.Reverse();
}
}
}
- Create Package:
# Build and create package
dotnet pack
# Or pack with specific configuration
dotnet pack --configuration Release --output ./nupkgs
Advanced Package Configuration
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Multi-targeting -->
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
<!-- Package metadata -->
<PackageId>MyCompany.MyPackage</PackageId>
<Version>1.2.3</Version>
<AssemblyVersion>1.2.0.0</AssemblyVersion>
<FileVersion>1.2.3.0</FileVersion>
<!-- Package details -->
<Title>My Awesome Package</Title>
<Authors>John Doe</Authors>
<Owners>MyCompany</Owners>
<Description>A comprehensive package for awesome functionality</Description>
<Summary>Short summary of the package</Summary>
<PackageTags>utility;helper;extensions</PackageTags>
<PackageReleaseNotes>
v1.2.3:
- Added new StringExtensions
- Fixed bug in IsPalindrome method
- Performance improvements
</PackageReleaseNotes>
<!-- Links -->
<PackageProjectUrl>https://github.com/mycompany/mypackage</PackageProjectUrl>
<RepositoryUrl>https://github.com/mycompany/mypackage</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<!-- Licensing -->
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<!-- Or use license file -->
<!-- <PackageLicenseFile>LICENSE.txt</PackageLicenseFile> -->
<!-- Icon and readme -->
<PackageIcon>icon.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<!-- Build settings -->
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup>
<!-- Include files in package -->
<None Include="README.md" Pack="true" PackagePath="\" />
<None Include="icon.png" Pack="true" PackagePath="\" />
<None Include="LICENSE.txt" Pack="true" PackagePath="\" />
</ItemGroup>
</Project>
Publishing Packages
Publishing to NuGet.org
-
Create Account: Register at nuget.org
-
Get API Key: Generate API key from your account settings
-
Publish Package:
# Publish to NuGet.org
dotnet nuget push MyPackage.1.0.0.nupkg --api-key YOUR_API_KEY --source https://api.nuget.org/v3/index.json
# Include symbols package
dotnet nuget push MyPackage.1.0.0.nupkg --api-key YOUR_API_KEY --source https://api.nuget.org/v3/index.json
dotnet nuget push MyPackage.1.0.0.snupkg --api-key YOUR_API_KEY --source https://api.nuget.org/v3/index.json
Publishing to Private Feed
# Publish to Azure DevOps feed
dotnet nuget push MyPackage.1.0.0.nupkg --api-key az --source https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json
# Publish to GitHub Packages
dotnet nuget push MyPackage.1.0.0.nupkg --api-key YOUR_GITHUB_TOKEN --source https://nuget.pkg.github.com/OWNER/index.json
Continuous Deployment
name: Publish NuGet Package
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --configuration Release --no-restore
- name: Test
run: dotnet test --configuration Release --no-build
- name: Pack
run: dotnet pack --configuration Release --no-build --output ./artifacts
- name: Publish to NuGet
run: dotnet nuget push ./artifacts/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json
Package Security and Best Practices
Security Considerations
# Check for vulnerable packages
dotnet list package --vulnerable
# Audit packages for known vulnerabilities
dotnet restore --audit
# Update vulnerable packages
dotnet add package VulnerablePackage --version SAFE_VERSION
Package Validation
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Enable package validation -->
<EnablePackageValidation>true</EnablePackageValidation>
<!-- Generate baseline for validation -->
<PackageValidationBaselineVersion>1.0.0</PackageValidationBaselineVersion>
</PropertyGroup>
</Project>
Best Practices
-
Versioning Strategy:
- Follow semantic versioning
- Use prerelease versions for testing
- Never delete published packages
-
Documentation:
- Include comprehensive README
- Provide XML documentation
- Add usage examples
-
Testing:
- Test packages before publishing
- Include unit tests in your package projects
- Test across target frameworks
-
Dependencies:
- Minimize dependencies
- Use the lowest compatible versions
- Avoid dependencies with known vulnerabilities
namespace MyCompany.Utilities
{
/// <summary>
/// Provides extension methods for string manipulation
/// </summary>
/// <example>
/// <code>
/// string text = "hello world";
/// string title = text.ToTitleCase(); // "Hello World"
/// </code>
/// </example>
public static class StringExtensions
{
/// <summary>
/// Converts a string to title case
/// </summary>
/// <param name="input">The input string</param>
/// <returns>The string in title case</returns>
/// <exception cref="ArgumentNullException">Thrown when input is null</exception>
public static string ToTitleCase(this string input)
{
if (input == null)
throw new ArgumentNullException(nameof(input));
if (string.IsNullOrEmpty(input))
return input;
return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(input.ToLower());
}
}
}
NuGet in Enterprise
Private Package Feeds
Enterprise organizations often need private package feeds:
- Azure DevOps Artifacts
- GitHub Packages
- JFrog Artifactory
- Sonatype Nexus
- MyGet
Package Management Policies
<!-- Directory.Packages.props -->
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
<PackageVersion Include="Serilog.AspNetCore" Version="7.0.0" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<!-- No version specified - managed centrally -->
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="Microsoft.EntityFrameworkCore" />
</ItemGroup>
</Project>
Troubleshooting Common Issues
Package Restore Issues
# Clear all caches
dotnet nuget locals all --clear
# Restore with no cache
dotnet restore --no-cache
# Restore with detailed logging
dotnet restore --verbosity detailed
# Force re-evaluation of all dependencies
dotnet restore --force
Version Conflicts
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<!-- Force specific version to resolve conflicts -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<!-- Override transitive dependency version -->
<PackageReference Include="System.Text.Json" Version="8.0.0" />
</ItemGroup>
</Project>
Authentication Issues
# Configure credentials for private feeds
dotnet nuget update source MyPrivateFeed --username myuser --password mytoken
# Use credential providers for Azure DevOps
dotnet tool install -g Azure.DevOps.Nuget.CredentialProvider
# Clear and reconfigure sources
dotnet nuget remove source MyPrivateFeed
dotnet nuget add source https://my-feed.com/nuget --name MyPrivateFeed
Summary
NuGet is the cornerstone of .NET package management, providing:
Key Benefits
- Productivity: Reuse existing solutions instead of building from scratch
- Quality: Leverage well-tested, community-vetted packages
- Ecosystem: Access to hundreds of thousands of packages
- Versioning: Reliable dependency management with semantic versioning
- Security: Built-in vulnerability scanning and security updates
Essential Skills
- Package Discovery: Finding the right packages for your needs
- Dependency Management: Understanding and resolving dependencies
- Version Control: Managing package versions effectively
- Security: Keeping packages updated and secure
- Package Creation: Building and sharing your own packages
Best Practices Summary
- Use specific versions in production
- Regularly update packages for security
- Minimize dependencies
- Test packages thoroughly
- Document your packages well
- Follow semantic versioning
Series Completion
Congratulations! You've completed the .NET Essentials Series. You now understand:
- ✅ What is .NET? - The platform and ecosystem
- ✅ CLR Basics - How .NET executes your code
- ✅ C# Programming - The primary .NET language
- ✅ Essential Libraries - Core .NET APIs and types
- ✅ CLI Commands - Development workflow and tools
- ✅ NuGet Packages - Package management and ecosystem
Next Steps
Now that you have a solid foundation in .NET, consider exploring:
- ASP.NET Core for web development
- Entity Framework Core for data access
- Blazor for interactive web UIs
- MAUI for cross-platform applications
- Advanced C# features like source generators
- Microservices architecture with .NET
Ready to build amazing .NET applications? PBX Digital specializes in modern .NET development. Contact us at mp@pbxdigital.net for expert consulting, development, and training services.
Continue learning with more tutorials in our documentation or explore advanced topics in our documentation.