--- name: package-management description: NuGet package management best practices including versioning strategies, central package management, and dependency resolution. Use when setting up Central Package Management (CPM), managing package versions across multiple projects, or resolving dependency conflicts in .NET solutions. --- # NuGet Package Management ## When to Use This Skill Use this skill when: - Adding, removing, or updating NuGet packages - Setting up Central Package Management (CPM) for a solution - Managing package versions across multiple projects - Troubleshooting package conflicts or restore issues --- ## Golden Rule: Never Edit XML Directly **Always use `dotnet` CLI commands to manage packages.** Never manually edit `.csproj` or `Directory.Packages.props` files. ```bash # DO: Use CLI commands dotnet add package Newtonsoft.Json dotnet remove package Newtonsoft.Json dotnet list package --outdated # DON'T: Edit XML directly # ``` **Why:** - CLI validates package exists and resolves correct version - Handles transitive dependencies correctly - Updates lock files if present - Avoids typos and malformed XML - Works correctly with CPM --- ## Central Package Management (CPM) CPM centralizes all package versions in one file, eliminating version conflicts across projects. ### Enable CPM Create `Directory.Packages.props` in solution root: ```xml true ``` ### Project Files with CPM Projects reference packages **without versions**: ```xml ``` ### Adding Packages with CPM ```bash # Adds to Directory.Packages.props AND project file dotnet add package Serilog.Sinks.Console # Result in Directory.Packages.props: # # Result in project file: # ``` --- ## Shared Version Variables Group related packages with shared version variables: ```xml true 1.5.59 1.5.59 9.0.0 1.11.0 2.9.2 ``` **Benefits:** - Update all Akka packages by changing one variable - Clear organization with labeled ItemGroups - Prevents version mismatches in related packages --- ## When NOT to Use CPM Central Package Management isn't always the right choice: ### Legacy Projects Migrating an existing large solution to CPM can introduce issues: - Existing version conflicts become visible all at once - Some packages may have intentional version differences - Migration requires touching many files simultaneously **Recommendation**: For legacy projects, migrate incrementally or stick with per-project versioning if it's working. ### Version Ranges CPM requires exact versions - it doesn't support version ranges: ```xml ``` If you need version ranges (rare, but some library scenarios require it), CPM won't work. ### Older .NET Versions CPM requires: - **.NET SDK 6.0.300+** or later - **NuGet 6.2+** or later - **Visual Studio 2022 17.2+** or later If you're targeting older SDK versions or have team members on older tooling, CPM may cause build failures. ### Multi-Repo Solutions If your solution spans multiple repositories that are built independently, CPM's single `Directory.Packages.props` won't help - each repo needs its own. --- ## CLI Command Reference ### Adding Packages ```bash # Add latest stable version dotnet add package Serilog # Add specific version dotnet add package Serilog --version 4.0.0 # Add prerelease dotnet add package Serilog --prerelease # Add to specific project dotnet add src/MyApp/MyApp.csproj package Serilog ``` ### Removing Packages ```bash # Remove from current project dotnet remove package Serilog # Remove from specific project dotnet remove src/MyApp/MyApp.csproj package Serilog ``` ### Listing Packages ```bash # List all packages in solution dotnet list package # Show outdated packages dotnet list package --outdated # Include transitive dependencies dotnet list package --include-transitive # Show vulnerable packages dotnet list package --vulnerable # Show deprecated packages dotnet list package --deprecated ``` ### Updating Packages ```bash # With CPM: Edit the version in Directory.Packages.props # Then restore to apply dotnet restore # Without CPM: Remove and add with new version dotnet remove package Serilog dotnet add package Serilog --version 4.1.0 # Or use dotnet-outdated tool (recommended) dotnet tool install --global dotnet-outdated-tool dotnet outdated --upgrade ``` ### Restore and Clean ```bash # Restore packages dotnet restore # Clear local cache (troubleshooting) dotnet nuget locals all --clear # Force restore (ignore cache) dotnet restore --force ``` --- ## Package Sources ### List Sources ```bash dotnet nuget list source ``` ### Add Private Feed ```bash # Add authenticated feed dotnet nuget add source https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json \ --name MyFeed \ --username az \ --password $PAT \ --store-password-in-clear-text ``` ### NuGet.config For solution-specific sources, create `NuGet.config`: ```xml ``` --- ## Common Patterns ### Development-Only Packages ```xml ``` ### Conditional Packages ```xml ``` ### Version Override (Escape Hatch) When you must override CPM for one project (rare): ```xml ``` **Warning**: This is detected by Slopwatch (see `dotnet/slopwatch` skill) as potential slop. --- ## Troubleshooting ### Version Conflicts ```bash # See full dependency tree dotnet list package --include-transitive # Find what's pulling in a specific package dotnet list package --include-transitive | grep -i "PackageName" ``` ### Restore Failures ```bash # Clear all caches dotnet nuget locals all --clear # Restore with detailed logging dotnet restore --verbosity detailed # Check for locked packages cat packages.lock.json ``` ### Lock Files For reproducible builds, use package lock files: ```xml true ``` Then commit `packages.lock.json` files. --- ## Anti-Patterns ### Don't: Edit XML Directly ```xml ``` ### Don't: Inline Versions with CPM ```xml ``` ### Don't: Mix Version Management ```xml ``` ### Don't: Forget Shared Variables ```xml ``` --- ## Quick Reference | Task | Command | |------|---------| | Add package | `dotnet add package ` | | Add specific version | `dotnet add package --version ` | | Remove package | `dotnet remove package ` | | List packages | `dotnet list package` | | Show outdated | `dotnet list package --outdated` | | Show vulnerable | `dotnet list package --vulnerable` | | Restore | `dotnet restore` | | Clear cache | `dotnet nuget locals all --clear` | --- ## Resources - **Central Package Management**: https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management - **dotnet CLI Reference**: https://learn.microsoft.com/en-us/dotnet/core/tools/ - **NuGet.config Reference**: https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file