Guide for Centralized Package Management (CPM) using Directory.Packages.props in .NET projects
This skill provides guidance for using Central Package Management (CPM) with Directory.Packages.props in this .NET 10 project. CPM manages all NuGet package versions in one central location.
Centralized Package Management (CPM) is a NuGet feature that centralizes package version management in a single Directory.Packages.props file at the solution root.
Benefits:
Traditional approach (NOT used in this project):
<!-- Each .csproj specifies versions -->
<PackageReference Include="MSTest" Version="4.0.0-preview.25465.3" />
CPM approach (used in this project):
<!-- Directory.Packages.props defines versions -->
<PackageVersion Include="MSTest" Version="4.0.0-preview.25465.3" />
<!-- .csproj references WITHOUT version -->
<PackageReference Include="MSTest" />
Located at solution root (/Directory.Packages.props):
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<ItemGroup Label="Core Packages">
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="10.0.0-rc.2.25502.107" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0-rc.2.25502.107" />
</ItemGroup>
<ItemGroup Label="Testing Packages">
<PackageVersion Include="MSTest" Version="4.0.0-preview.25465.3" />
<PackageVersion Include="Microsoft.Playwright.MSTest.v4" Version="1.55.0-beta-4" />
</ItemGroup>
</Project>
ManagePackageVersionsCentrally: Enables CPM. All versions must be in Directory.Packages.props.
CentralPackageTransitivePinningEnabled: Pins transitive dependency versions to prevent unexpected updates.
CPM works alongside Directory.Build.props which defines shared MSBuild properties:
<Project>
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>disable</Nullable>
<ImplicitUsings>disable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
</Project>
Step 1: Add version to Directory.Packages.props
<ItemGroup Label="Your Category">
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
Step 2: Add reference to .csproj (WITHOUT version)
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
</ItemGroup>
Adding MSTest (already in project):
<!-- Directory.Packages.props -->
<PackageVersion Include="MSTest" Version="4.0.0-preview.25465.3" />
<!-- tests/ClaudeStack.Web.Tests/ClaudeStack.Web.Tests.csproj -->
<PackageReference Include="MSTest" />
Adding Razor Runtime Compilation (already in project):
<!-- Directory.Packages.props -->
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="10.0.0-rc.2.25502.107" />
<!-- src/ClaudeStack.Web/ClaudeStack.Web.csproj -->
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" />
WRONG - Adding Version to .csproj:
<!-- This will FAIL with CPM enabled -->
<PackageReference Include="MSTest" Version="4.0.0-preview.25465.3" />
Error message:
error NU1008: Version information is not allowed for central package versions.
CORRECT - No Version in .csproj:
<PackageReference Include="MSTest" />
When using dotnet add package, you MUST add the version separately:
# Step 1: Add to Directory.Packages.props manually
# Edit Directory.Packages.props and add:
# <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
# Step 2: Add reference to project
dotnet add src/ClaudeStack.Web/ClaudeStack.Web.csproj package Newtonsoft.Json
# OR manually add to .csproj:
# <PackageReference Include="Newtonsoft.Json" />
Note: dotnet add package may not automatically update Directory.Packages.props. Manual editing is often required.
Edit Directory.Packages.props:
<!-- Before -->
<PackageVersion Include="MSTest" Version="4.0.0-preview.25465.3" />
<!-- After -->
<PackageVersion Include="MSTest" Version="4.0.0" />
This updates the package across all projects that reference it.
Edit versions in Directory.Packages.props. All projects will use the new versions automatically.
# List outdated packages
dotnet list package --outdated
# Update packages in Directory.Packages.props based on output
# (Manual process - edit Directory.Packages.props)
# Restore to apply changes
dotnet restore
CPM supports version ranges, but not recommended for this project:
<!-- Avoid this pattern -->
<PackageVersion Include="MSTest" Version="[4.0.0,5.0.0)" />
Use explicit versions for reproducibility.
This project uses labeled ItemGroups for organization:
<ItemGroup Label="Core Packages">
<!-- ASP.NET Core packages -->
</ItemGroup>
<ItemGroup Label="Testing Packages">
<!-- MSTest, Playwright, etc. -->
</ItemGroup>
<ItemGroup Label="Analysis Packages">
<!-- Code analysis tools -->
</ItemGroup>
Labels are optional but improve readability.
Core Packages:
Testing Packages:
# List all packages in solution
dotnet list package
# Include transitive dependencies
dotnet list package --include-transitive
Full Error:
error NU1008: Version information is not allowed for central package versions.
Cause: PackageReference in .csproj includes Version attribute when CPM is enabled.
Solution: Remove Version from .csproj
<!-- WRONG -->
<PackageReference Include="MSTest" Version="4.0.0-preview.25465.3" />
<!-- CORRECT -->
<PackageReference Include="MSTest" />
Cause: Package version not defined in Directory.Packages.props.
Solution: Add to Directory.Packages.props:
<PackageVersion Include="PackageName" Version="x.y.z" />
Symptom: Project A uses v1.0, Project B uses v2.0 of same package.
Cause: With CPM, all projects must use the same version. This is by design.
Solutions:
VersionOverride<!-- In .csproj, override version (not recommended) -->
<PackageReference Include="MSTest" VersionOverride="3.0.0" />
Symptom: Build errors about incompatible transitive dependencies.
Solution: Enable CentralPackageTransitivePinningEnabled:
<PropertyGroup>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
Already enabled in this project.
Symptom: dotnet add package adds reference but version is missing from Directory.Packages.props.
Solution: Manually add version to Directory.Packages.props (this is expected behavior).
Solution: Ensure package exists on NuGet.org or configured feeds:
# Clear NuGet cache
dotnet nuget locals all --clear
# Restore
dotnet restore
When adding a new package:
<PackageVersion> to Directory.Packages.props<PackageReference> to .csprojAvoid mixing preview and stable versions unnecessarily. This project uses preview packages because it targets .NET 10 RC 2.
Understand version numbers: Major.Minor.Patch[-Prerelease]
10.0.0-rc.2.25502.107: Major=10, Minor=0, Patch=0, Prerelease=rc.2.25502.107Use labeled ItemGroups:
dotnet list package --include-transitive
Understand what indirect dependencies your project uses.
When updating packages:
When updating major versions, document breaking changes in commit messages or project documentation.
Only use VersionOverride as a last resort. It defeats the purpose of CPM.
/Directory.Packages.props - Package versions (central)
/Directory.Build.props - Shared build properties
/**/*.csproj - Package references (no versions)
<!-- Step 1: Directory.Packages.props -->
<PackageVersion Include="PackageName" Version="x.y.z" />
<!-- Step 2: ProjectFile.csproj -->
<PackageReference Include="PackageName" />
<!-- Directory.Packages.props - change version -->
<PackageVersion Include="PackageName" Version="x.y.z" />
<!-- All projects automatically use new version -->
# List packages
dotnet list package
# List outdated packages
dotnet list package --outdated
# List transitive dependencies
dotnet list package --include-transitive
# Restore packages
dotnet restore
# Clear cache and restore
dotnet nuget locals all --clear && dotnet restore
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<ItemGroup Label="Category Name">
<PackageVersion Include="PackageName" Version="x.y.z" />
</ItemGroup>
</Project>
| Error | Cause | Solution |
|---|---|---|
| NU1008 | Version in .csproj | Remove Version attribute |
| Package not found | Missing from Directory.Packages.props | Add PackageVersion |
| Version conflict | Different versions needed | Use single version or VersionOverride |
This project uses:
CPM is a stable NuGet feature as of .NET 6.0 SDK.