NuGet
What is NuGet?
NuGet is .NET’s package manager - it’s how you add third-party libraries and tools to your projects. Think of it as the central place where .NET developers share and consume reusable code.
If you’ve used other languages, NuGet is .NET’s equivalent to:
- npm (Node.js/JavaScript)
- pip (Python)
- Maven/Gradle (Java)
- Cargo (Rust)
- RubyGems (Ruby)
Instead of copying code or DLLs around, you simply declare “I need this library” and NuGet handles downloading it and all its dependencies.
Why Use NuGet?
1. No Reinventing the Wheel
Need to work with JSON? Parse CSV files? Connect to a database? Someone’s already built a great library for that:
dotnet add package Newtonsoft.Json
dotnet add package CsvHelper
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
2. Dependency Management
NuGet automatically handles dependencies. If package A needs package B, NuGet installs both:
# You install Entity Framework...
dotnet add package Microsoft.EntityFrameworkCore
# ...NuGet automatically installs all its dependencies
# - Microsoft.EntityFrameworkCore.Abstractions
# - Microsoft.EntityFrameworkCore.Analyzers
# - Microsoft.Extensions.Caching.Memory
# - And several others
3. Version Control
NuGet manages package versions, making it easy to upgrade or stay on specific versions:
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Serilog" Version="3.1.1" />
How NuGet Works
When you add a package, two things happen:
1. Your .csproj File is Updated
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
</ItemGroup>
</Project>
2. Packages are Downloaded
Packages are downloaded to a global cache on your machine (usually ~/.nuget/packages on Linux/Mac or %userprofile%\.nuget\packages on Windows). Your project references them from there.
Common NuGet Commands
Adding Packages
# Add the latest version
dotnet add package Serilog
# Add a specific version
dotnet add package Serilog --version 3.1.1
# Add a pre-release version
dotnet add package MyPackage --prerelease
Removing Packages
dotnet remove package Serilog
Updating Packages
# Update all packages
dotnet list package --outdated
dotnet add package Serilog # Installs latest
# Or manually edit .csproj and change version number
Restoring Packages
When you clone a project, packages aren’t included. Restore them with:
dotnet restore
# Or just build/run - restore happens automatically
dotnet build
dotnet run
NuGet.org - The Package Registry
NuGet.org is the main public registry where packages are hosted. It’s like npm’s registry or Python’s PyPI.
Popular .NET API packages include:
- Entity Framework Core - ORM for database access
- Swashbuckle - Swagger/OpenAPI documentation
- Serilog - Structured logging
- AutoMapper - Object-to-object mapping
- FluentValidation - Input validation
- Dapper - Lightweight ORM
- MediatR - CQRS/Mediator pattern
- Polly - Resilience and fault handling
Practical Example - Building an API
Here’s what a typical API’s package references might look like:
<ItemGroup>
<!-- Web Framework -->
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" />
<!-- Database -->
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" />
<!-- Documentation -->
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<!-- Logging -->
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
<!-- Validation -->
<PackageReference Include="FluentValidation.AspNetCore" Version="11.3.0" />
<!-- Testing (in test project) -->
<PackageReference Include="xUnit" Version="2.6.1" />
<PackageReference Include="Moq" Version="4.20.69" />
</ItemGroup>
Package Versions
NuGet uses semantic versioning (SemVer): Major.Minor.Patch
<!-- Exact version -->
<PackageReference Include="Serilog" Version="3.1.1" />
<!-- Minimum version -->
<PackageReference Include="Serilog" Version="3.1.1" />
<!-- This allows 3.1.1, 3.1.2, 3.2.0, but not 4.0.0 -->
<!-- Version range -->
<PackageReference Include="Serilog" Version="[3.1.1,4.0.0)" />
<!-- Allows 3.1.1 up to (but not including) 4.0.0 -->
Most of the time, you’ll just specify the version and .NET will handle updates within the same major version.
Private NuGet Feeds
Organizations often host their own private NuGet feeds for internal packages:
<!-- nuget.config -->
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="CompanyFeed" value="https://nuget.company.com/feed" />
</packageSources>
</configuration>
Common private feed providers:
- Azure Artifacts
- GitHub Packages
- MyGet
- ProGet
- JFrog Artifactory
Creating Your Own Package
If you build a reusable library, you can publish it as a NuGet package:
# Pack your project
dotnet pack
# Publish to NuGet.org (requires API key)
dotnet nuget push MyPackage.1.0.0.nupkg --api-key YOUR_API_KEY --source https://api.nuget.org/v3/index.json
Transitive Dependencies
NuGet handles “dependencies of dependencies” automatically:
Your Project
└─ Entity Framework Core 8.0.0
├─ Microsoft.EntityFrameworkCore.Abstractions 8.0.0
├─ Microsoft.EntityFrameworkCore.Analyzers 8.0.0
├─ Microsoft.Extensions.Caching.Memory 8.0.0
│ └─ Microsoft.Extensions.DependencyInjection.Abstractions 8.0.0
└─ Several other packages...
You only need to reference Entity Framework Core - NuGet handles the rest.
Visual Studio vs CLI
You can manage packages in two ways:
Visual Studio (GUI)
Right-click project → Manage NuGet Packages → Browse/Installed/Updates
Command Line (dotnet CLI)
dotnet add package PackageName
dotnet remove package PackageName
dotnet list package
Both do the same thing - it’s just personal preference. The CLI is more common in modern .NET development and works everywhere (Windows, Mac, Linux).
Common Packages for APIs
Here are packages you’ll frequently use when building .NET APIs:
Database
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
dotnet add package Microsoft.EntityFrameworkCore.Design
Logging
dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.Console
Documentation
dotnet add package Swashbuckle.AspNetCore
Validation
dotnet add package FluentValidation.AspNetCore
Testing
dotnet add package xunit
dotnet add package Moq
dotnet add package Microsoft.AspNetCore.Mvc.Testing
Package Vulnerabilities
NuGet helps identify security issues:
# Check for vulnerable packages
dotnet list package --vulnerable
# Example output:
# The following sources were used:
# https://api.nuget.org/v3/index.json
#
# Project `MyApi` has the following vulnerable packages
# [net8.0]:
# Top-level Package Requested Resolved Severity Advisory URL
# > Newtonsoft.Json 12.0.1 12.0.1 High https://github.com/advisories/...
Then update the vulnerable package:
dotnet add package Newtonsoft.Json
Wrap Up
NuGet is simple but essential - it’s how the .NET ecosystem shares code. Rather than building everything from scratch, you leverage thousands of well-tested libraries built by the community.
Key takeaways:
- Use
dotnet add packageto add libraries - Packages are declared in your .csproj file
- Dependencies are automatic - NuGet handles transitive dependencies
- Versions matter - understand semantic versioning
- Security counts - check for vulnerabilities regularly
The beauty of NuGet is that it “just works” - add a package, start using it. No complex configuration, no DLL hell, no manual dependency tracking. It’s one of those tools that disappears into the background, letting you focus on building your API instead of managing libraries.