Skip to content

NuGet — Package Management Complete Guide

DodaTech Updated 2026-06-20 6 min read

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
â„šī¸ Info

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

  1. NU1107: Version conflict: Two packages require different versions of the same dependency. Use dotnet list package --vulnerable to diagnose and add a PackageReference with the winning version directly.

  2. NU1603: Dependency specified without version: A transitive dependency appears without a version constraint. Add an explicit version or update the referring package.

  3. 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.

  4. Package restore failed — offline: dotnet restore needs internet (unless using a local cache). Run dotnet nuget locals all --clear then retry with a network connection.

  5. NU5041: Missing icon in package: Modern NuGet client requires an icon URL. Add <PackageIconUrl> or <PackageIcon> to .csproj.

  6. Package not found after publish: NuGet.org indexes packages within 15–30 minutes or you can use https://www.myget.org for instant publishing. Check your package source configuration.

  7. DLL Hell — multiple versions of same assembly: The binding redirects issue. Use <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> in .csproj for .NET Framework projects.

Practice Questions

  1. What file extension does a NuGet package use?
  2. Which command installs a package via the dotnet CLI?
  3. How do you add a private NuGet source?
  4. What does dotnet nuget audit do?
  5. What is the difference between PackageReference and packages.config?

Answers:

  1. .nupkg
  2. dotnet add package <PackageName>
  3. Use dotnet nuget add source <URL> -name <Name> or edit nuget.config
  4. Scans your project's packages for known security vulnerabilities using the GitHub Advisory Database
  5. 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.

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

Is NuGet free to use?

Yes. Hosting packages on nuget.org is free for open-source packages. Private feeds on Azure Artifacts have a free tier (2 GB storage). Self-hosted feeds are completely free.

How do I update all packages in a project?

Run dotnet list package --outdated to see available updates, then dotnet update package <name> for each. For bulk updates, use Visual Studio's NuGet Package Manager UI or tools like dotnet-outdated.

What happens if a NuGet package has a security vulnerability?

NuGet 6.8+ shows a warning during restore. Run dotnet nuget audit to scan explicitly. If a critical vulnerability is found, update to the patched version or find an alternative.

Try It Yourself

▶ Try It YourselfEdit the code and click Run

What's Next

.NET CLI — Command Line Complete Guide
MSBuild — Build Automation Complete Guide
Azure DevOps — CI/CD Pipelines Complete Guide

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro