NuGet â Package Management Complete Guide
In this tutorial, you'll learn about NuGet. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
NuGet is the official package manager for the .NET ecosystem, enabling developers to create, share, and consume reusable libraries through a centralized feed with built-in dependency resolution and versioning.
What You'll Learn
You'll understand how NuGet works â from installing packages via the CLI and Visual Studio to creating your own packages, managing dependencies, setting up private feeds, and following security best practices.
Why NuGet Matters
Every real .NET project depends on NuGet packages. The average project references 50+ packages. Understanding NuGet deeply means faster development, fewer dependency conflicts, and fewer supply-chain security risks. DodaTech's DodaZIP and Durga Antivirus Pro each rely on internal NuGet feeds for shared components.
Real-World Use
A team maintains ten Microservices sharing common logging and authentication libraries. Instead of copying code, they publish shared packages to a private NuGet feed. When a security fix is needed, one package update rolls out to all services.
NuGet Learning Path
flowchart LR A[".NET SDK Basics"] --> B["What Is NuGet?"] B --> C["Installing & Using Packages"] C --> D["Creating NuGet Packages"] D --> E["Private Feeds & CI/CD"] E --> F["Package Security & Auditing"] D:::current classDef current fill:#f90,color:#fff,stroke:#333,stroke-width:2px
Prerequisites: .NET SDK 6+ installed, basic familiarity with the C# language and dotnet-cli commands.
What Is a NuGet Package?
A NuGet package is a .nupkg file â a ZIP archive containing compiled code (DLLs), metadata (.nuspec), and content files. It's the .NET equivalent of npm packages for Node.js or gems for Ruby.
Installing and Managing Packages
Using dotnet CLI
# Install a package (adds to .csproj)
dotnet add package Newtonsoft.Json --version 13.0.3
# Install latest version
dotnet add package Serilog
# List all packages in a project
dotnet list package
# Remove a package
dotnet remove package Newtonsoft.Json
Using Package Manager Console (Visual Studio)
Install-Package Dapper -Version 2.1.28
Update-Package Dapper
Uninstall-Package Dapper
Package Reference Formats
| Format | Location | Use Case |
|---|---|---|
| PackageReference | .csproj file |
Modern .NET (SDK-style) |
| packages.config | packages.config |
Legacy .NET Framework |
global.json |
project root | Pin SDK version, not packages |
A PackageReference entry in .csproj looks like:
<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.28" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
</ItemGroup>
Creating a NuGet Package
Step 1: Create a Class Library
dotnet new classlib -n DodaTech.SecurityUtils
cd DodaTech.SecurityUtils
Step 2: Add Package Metadata in .csproj
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<PackageId>DodaTech.SecurityUtils</PackageId>
<Version>1.0.0</Version>
<Authors>DodaTech</Authors>
<Description>Security utility library for hashing, encryption, and
input validation used across DodaTech products.</Description>
<PackageTags>security;hashing;encryption;validation</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryUrl>https://github.com/dodatech/security-utils</RepositoryUrl>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
Step 3: Build and Pack
# Build and create .nupkg
dotnet pack -c Release
# Publish to nuget.org
dotnet nuget push bin/Release/DodaTech.SecurityUtils.1.0.0.nupkg \
--api-key YOUR_API_KEY \
--source https://api.nuget.org/v3/index.json
Expected output:
Pushing DodaTech.SecurityUtils.1.0.0.nupkg to 'https://api.nuget.org/v3/index.json'...
PUT https://api.nuget.org/v3/index.json
Created https://www.nuget.org/packages/DodaTech.SecurityUtils/1.0.0 17.60 kB
Code Example: Using a NuGet Package Programmatically
using Dapper;
using Microsoft.Data.SqlClient;
using System.Data;
var connection = new SqlConnection("Server=.;Database=SecurityLogs;Trusted_Connection=true;");
var results = connection.Query("SELECT * FROM ThreatEvents WHERE Severity > 3");
foreach (var row in results)
{
Console.WriteLine($"Event: {row.EventName}, Severity: {row.Severity}");
}
Private NuGet Feeds
For enterprise teams, public nuget.org is not appropriate. Set up a private feed:
1. Local Folder Feed
# Add a local folder as a NuGet source
dotnet nuget add source \\server\packages -name "TeamPackages"
# OR using nuget.config
2. Azure Artifacts Feed
# Add Azure DevOps artifact source
dotnet nuget add source https://pkgs.dev.azure.com/yourorg/_packaging/FeedName/nuget/v3/index.json \
--name "AzureArtifacts" \
--username "any" \
--password YOUR_PAT
nuget.config Example
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="DodaTech Internal" value="https://pkgs.dev.azure.com/dodatech/_packaging/internal/nuget/v3/index.json" />
</packageSources>
<disabledPackageSources />
</configuration>
Security: Package Supply Chain
This is critical. A compromised NuGet package can inject malware into your build.
Package Security Best Practices
| Practice | Why |
|---|---|
| Pin exact versions | Avoid auto-updating to compromised versions |
Use nuget audit |
Scan for known vulnerabilities (NuGet 6.8+) |
| Trusted authors only | Vet package authors before adding |
| Lock files | Enable restorePackagesWithLockFile for reproducible builds |
| Private feed upstream | Proxy public feed through your private feed to audit packages |
Audit Command
# Check for vulnerable packages
dotnet nuget audit
Common Errors
NU1107: Version conflict: Two packages require different versions of the same dependency. Use
dotnet list package --vulnerableto diagnose and add aPackageReferencewith the winning version directly.NU1603: Dependency specified without version: A transitive dependency appears without a version constraint. Add an explicit version or update the referring package.
Access denied on push: Your API key is invalid or expired. Generate a new one from nuget.org â API Keys. For Azure Artifacts, use a Personal Access Token with Packaging scope.
Package restore failed â offline:
dotnet restoreneeds internet (unless using a local cache). Rundotnet nuget locals all --clearthen retry with a network connection.NU5041: Missing icon in package: Modern NuGet client requires an icon URL. Add
<PackageIconUrl>or<PackageIcon>to.csproj.Package not found after publish: NuGet.org indexes packages within 15â30 minutes or you can use
https://www.myget.orgfor instant publishing. Check your package source configuration.DLL Hell â multiple versions of same assembly: The binding redirects issue. Use
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>in.csprojfor .NET Framework projects.
Practice Questions
- What file extension does a NuGet package use?
- Which command installs a package via the dotnet CLI?
- How do you add a private NuGet source?
- What does
dotnet nuget auditdo? - What is the difference between PackageReference and packages.config?
Answers:
.nupkgdotnet add package <PackageName>- Use
dotnet nuget add source <URL> -name <Name>or editnuget.config - Scans your project's packages for known security vulnerabilities using the GitHub Advisory Database
- PackageReference is the modern format (SDK-style projects, transitive dependencies); packages.config is legacy (.NET Framework, flat list)
Challenge
Create a NuGet package that provides a single extension method string.ToSlug() which converts a string to a URL-friendly slug (lowercase, hyphenated, no special chars). Package it, push it to a local folder feed, and consume it from another project.
Real-World Task
Audit a real .NET project (like one from GitHub) using dotnet list package --vulnerable. For each vulnerable package found, research the CVE, determine if your code is affected, and update to a patched version. Document your findings.
Featured Snippet
What is NuGet?
NuGet is the official package manager for .NET that allows developers to create, publish, and consume reusable libraries as packages, with built-in dependency resolution, versioning, and support for private feeds.
FAQ
Try It Yourself
What's Next
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro