Two copies of the same solution:
| Folder | State |
|---|---|
before/ |
Four projects, versions scattered across four .csproj files |
after/ |
Same solution after migrating to Central Package Management |
Both build on the .NET 8 SDK or newer. before/ is the on-camera starting point — reset to it between takes with git checkout -- before/.
| Project | Newtonsoft.Json | Serilog | Serilog.Sinks.Console |
|---|---|---|---|
Shop.Domain |
13.0.1 | – | – |
Shop.Api |
13.0.3 | 3.1.1 | 5.0.0 |
Shop.Worker |
13.0.1 | 4.0.0 | 6.1.1 |
Shop.DataMigrator |
– | (transitive) | 6.1.1 |
Shop.DataMigrator never references Serilog directly — it arrives through Serilog.Sinks.Console, which asks for Serilog >= 4.0.0. That is the project used for the transitive-pinning segment.
cd before
grep -rn "PackageReference" --include=*.csproj .
dotnet build
dotnet run --project src/Shop.Api
dotnet run --project src/Shop.WorkerTwo projects in one solution, two different Newtonsoft.Json assemblies. It builds green.
dotnet new packagesprops # scaffolds Directory.Packages.propsThen set ManagePackageVersionsCentrally to true and move every version into PackageVersion items.
Leave one Version= behind on a PackageReference and restore:
error NU1008: Projects that use central package version management should not define
the version on the PackageReference items but on the PackageVersion items: Newtonsoft.Json.
Add a PackageReference with no matching PackageVersion:
error NU1010: The PackageReference items Foo.Bar do not have corresponding PackageVersion.
Shop.Api in after/ is deliberately held back:
<PackageReference Include="Serilog" VersionOverride="3.1.1" />To ban that repo-wide, add to Directory.Packages.props:
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>which turns the override into:
error NU1013: The package reference Serilog specifies a VersionOverride but the ability
to override a centrally defined version is currently disabled.
after/ has CentralPackageTransitivePinningEnabled set to true and pins Serilog at 4.4.0.
Shop.DataMigrator has no direct Serilog reference, yet resolves 4.4.0 instead of the 4.0.0 the sink asked for:
cd after
dotnet list tools/Shop.DataMigrator/Shop.DataMigrator.csproj package --include-transitive
dotnet run --project tools/Shop.DataMigratorTry to pin below what a dependency demands and restore fails:
error NU1109: Detected package downgrade: Serilog from 4.0.0 to centrally defined 3.1.1.
Update the centrally managed package version to a higher version.
One line in Directory.Packages.props puts the analyzer package into all four projects with
PrivateAssets="All" applied automatically — nothing flows to consumers of your NuGet packages.
- Only the closest
Directory.Packages.propsis used. A nested one replaces the root one; import the parent explicitly with$([MSBuild]::GetPathOfFileAbove(...))if you want both. - With more than one package source configured, CPM logs NU1507 — fix it with package source mapping or a single source.
- Multi-targeting: put a
Conditionon thePackageVersionitem, not on thePackageReference. - Opt one project out with
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>.