NuGet
Package Manager
NuGet
Overview
NuGet is the official package manager for the .NET ecosystem, providing tools for .NET developers to efficiently share and consume libraries. Fully integrated with Visual Studio and dotnet CLI, it offers modern dependency management through PackageReference format, Central Package Management (CPM), and efficient storage via Global Packages Folder. Since NuGet 6.8 released in 2024, features like NuGetAudit for vulnerability detection, security enhancements, and HTTPS enforcement have been implemented, creating a safer and more reliable .NET development environment.
Details
NuGet was developed by Microsoft in 2010 and has established itself as the standard package manager for the .NET ecosystem. The transition from the legacy packages.config format to PackageReference format has deepened integration with MSBuild, enabling direct dependency management within project files. Since NuGet 6.8, the NuGetAudit feature automatically detects packages with known vulnerabilities and displays warnings to developers. Central Package Management (CPM) functionality enables version unification and transitive dependency security management in large-scale projects. Complete integration with Visual Studio, Visual Studio Code, and dotnet CLI provides seamless package operations from both GUI and CLI interfaces.
Pros and Cons
Pros
- Complete Visual Studio integration: Unified operation experience from both GUI and CLI
- PackageReference format: Direct dependency management within project files
- Automatic restoration: Automatic package restoration during build without manual operations
- Vulnerability detection: Automatic security auditing through NuGetAudit functionality
- Central Package Management: Version unification management for large-scale projects
- Global cache: Efficient storage through Global Packages Folder
- Rich ecosystem: Vast package library centered around NuGet.org
Cons
- Windows dependency: Primarily optimized for Windows/.NET environments
- Learning curve: Concept understanding required during PackageReference migration
- Version conflicts: Difficulty resolving conflicts in complex dependency scenarios
- Performance: Increased restoration time with large numbers of packages
- Security risks: Vulnerability risks from third-party packages
- Network dependency: Dependency on online package sources
Reference Links
- NuGet Official Site
- NuGet Documentation
- NuGet.org - Package Repository
- NuGet Gallery
- NuGet Release Notes
- dotnet CLI Documentation
Code Examples
Basic Package Management
# Package operations with .NET CLI
dotnet add package Newtonsoft.Json
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package AutoMapper
# Installation with version specification
dotnet add package Serilog --version 3.1.1
dotnet add package Microsoft.Extensions.Logging --version 8.0.0
# Package removal
dotnet remove package Newtonsoft.Json
# Package restoration
dotnet restore
# Package listing
dotnet list package
dotnet list package --outdated
dotnet list package --vulnerable
PackageReference (Project File) Configuration
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.1" />
<PackageReference Include="AutoMapper" Version="12.0.1" />
<PackageReference Include="Serilog" Version="3.1.1" />
<PackageReference Include="FluentValidation" Version="11.9.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<!-- Development packages -->
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit" Version="2.6.6" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
Central Package Management (CPM) Configuration
<!-- Directory.Packages.props -->
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<ItemGroup>
<!-- Centrally managed versions -->
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.1" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.1" />
<PackageVersion Include="AutoMapper" Version="12.0.1" />
<PackageVersion Include="Serilog" Version="3.1.1" />
<PackageVersion Include="FluentValidation" Version="11.9.0" />
<!-- Test packages -->
<PackageVersion Include="xunit" Version="2.6.6" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.6" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
</ItemGroup>
</Project>
<!-- Project file (when using CPM) -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<!-- Versions managed in Directory.Packages.props -->
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="Microsoft.EntityFrameworkCore" />
<PackageReference Include="AutoMapper" />
<PackageReference Include="Serilog" />
</ItemGroup>
</Project>
Security Auditing and NuGetAudit
# Vulnerability scanning
dotnet list package --vulnerable
dotnet list package --vulnerable --include-transitive
# Security audit reports
dotnet restore --verbosity normal # Automatic audit during restore
# Detailed vulnerability information
dotnet list package --vulnerable --source nuget.org
<!-- NuGetAudit configuration -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Audit level settings -->
<NuGetAudit>true</NuGetAudit>
<NuGetAuditMode>all</NuGetAuditMode>
<NuGetAuditLevel>low</NuGetAuditLevel>
<!-- Treat warnings as errors -->
<WarningsAsErrors />
<WarningsNotAsErrors>NU1901;NU1902;NU1903;NU1904</WarningsNotAsErrors>
</PropertyGroup>
</Project>
Package Source Configuration
<!-- 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="MyGet V3" value="https://www.myget.org/F/my-feed/api/v3/index.json" />
<add key="Private Feed" value="https://pkgs.dev.azure.com/myorg/_packaging/my-feed/nuget/v3/index.json" />
</packageSources>
<packageSourceMapping>
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
<packageSource key="Private Feed">
<package pattern="MyCompany.*" />
<package pattern="Internal.*" />
</packageSource>
</packageSourceMapping>
<packageSourceCredentials>
<Private_Feed>
<add key="Username" value="[TOKEN]" />
<add key="ClearTextPassword" value="[PERSONAL_ACCESS_TOKEN]" />
</Private_Feed>
</packageSourceCredentials>
<config>
<add key="globalPackagesFolder" value="C:\nuget\packages" />
<add key="repositoryPath" value="packages" />
<add key="defaultPushSource" value="https://api.nuget.org/v3/index.json" />
</config>
</configuration>
Package Creation and Publishing
# Package creation
dotnet pack --configuration Release
# Specific output directory
dotnet pack --output ./nupkgs
# Version specification
dotnet pack -p:PackageVersion=1.2.3
# Publishing to NuGet.org
dotnet nuget push MyPackage.1.0.0.nupkg --api-key [API_KEY] --source https://api.nuget.org/v3/index.json
# Publishing to private feed
dotnet nuget push MyPackage.1.0.0.nupkg --source "Private Feed"
<!-- Package metadata configuration -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<!-- Package information -->
<PackageId>MyCompany.MyLibrary</PackageId>
<PackageVersion>1.2.3</PackageVersion>
<Authors>My Company</Authors>
<Company>My Company Inc.</Company>
<Product>My Library</Product>
<Description>A useful library for .NET development</Description>
<PackageTags>utility;helper;dotnet</PackageTags>
<PackageProjectUrl>https://github.com/mycompany/mylibrary</PackageProjectUrl>
<RepositoryUrl>https://github.com/mycompany/mylibrary</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<!-- Packaging settings -->
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
</Project>
Advanced Configuration and Troubleshooting
# Clear cache
dotnet nuget locals all --clear
dotnet nuget locals http-cache --clear
dotnet nuget locals global-packages --clear
# Detailed logging
dotnet restore --verbosity detailed
dotnet restore --no-cache
# Offline restoration
dotnet restore --source ./packages --source https://api.nuget.org/v3/index.json
# Multiple target frameworks
dotnet restore --framework net8.0
dotnet restore --framework net48
# Display package dependencies
dotnet list package --include-transitive
dotnet list package --framework net8.0
Visual Studio Integration
// PackageReference usage example
using Newtonsoft.Json;
using Microsoft.EntityFrameworkCore;
using AutoMapper;
using Serilog;
public class ExampleService
{
private readonly ILogger _logger;
private readonly IMapper _mapper;
public ExampleService(IMapper mapper)
{
_logger = Log.ForContext<ExampleService>();
_mapper = mapper;
}
public async Task<string> ProcessDataAsync(object data)
{
_logger.Information("Processing data: {@Data}", data);
// Using Newtonsoft.Json
var jsonData = JsonConvert.SerializeObject(data);
// Using AutoMapper
var mappedData = _mapper.Map<TargetType>(data);
return jsonData;
}
}