NuGet for solutions with multiple projects
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
In a .NET solution with multiple projects, NuGet works at the project level, not at the solution level in the abstract. That sounds obvious, but it explains most confusion: every project has its own package references, and the solution is mainly the place where you coordinate versions, restore behavior, and shared build conventions.
Start with PackageReference
Modern .NET projects normally declare NuGet dependencies directly in the project file.
A simple example:
If three projects need the same package, each project usually gets its own PackageReference. NuGet restore then resolves the right dependency graph for each build.
That is important because different projects in the same solution may have different roles:
- a web app
- a class library
- a test project
- a console tool
Not every project should reference every package just because they live in the same solution.
Centralize Versions with Directory.Packages.props
When several projects need the same package version, repeating the version string in every .csproj quickly becomes noisy and error-prone. The modern answer is central package management.
Create a Directory.Packages.props file in the solution root:
Then each project can reference the package without repeating the version:
This keeps versions consistent across the solution while still letting each project opt into only the packages it actually uses.
Reference Projects, Not Internal DLL Packages
Inside one solution, your own code should usually be connected with project references, not private NuGet packages.
Example:
Use ProjectReference when:
- the projects are developed together
- they are versioned together
- you want local changes to flow through during development
Use a NuGet package for an internal library only when you want an explicit publish and consume workflow across repositories, teams, or release boundaries.
Restore and Build the Whole Solution
NuGet restore can run on the whole solution, which is how you keep a multi-project workspace reproducible.
This restores all project dependencies and resolves transitive packages according to each project graph.
For example, if WebApp references CoreLibrary, and CoreLibrary references Dapper, WebApp may get access to that dependency transitively at build time depending on project type and asset flow. You should still keep direct dependencies explicit when your project actually uses them. That makes intent clearer and avoids surprises.
Handling Different Package Needs Across Projects
In a real solution, package usage is rarely uniform.
Example structure:
- '
MyApp.Webneeds ASP.NET Core packages' - '
MyApp.Coreneeds validation or serialization libraries' - '
MyApp.Testsneeds xUnit and test helpers'
That means the right setup is usually not "install this package on the whole solution." It is "install this package on the projects that need it, while managing versions centrally where useful."
A test project might look like this:
Those packages belong in the test project only, even if the solution contains many projects.
Packing Your Own Project as a NuGet Package
If one project in the solution should become a reusable package for other solutions, you can pack it directly.
That creates a .nupkg artifact you can publish to NuGet.org or to a private feed. This is separate from using NuGet to manage third-party dependencies inside the current solution.
Common Pitfalls
The biggest mistake is treating the solution as if it owned one shared package list for all projects. NuGet restore works through project dependency graphs, so package references still belong to individual projects.
Another issue is mixing old packages.config habits with modern PackageReference guidance. Current .NET projects are generally simpler and easier to manage with PackageReference and central package management.
Teams also over-share dependencies. Installing a package into every project "just in case" creates clutter and can make the dependency graph harder to maintain.
Finally, do not confuse project references with NuGet packaging strategy. Use ProjectReference for code that is developed together, and reserve internal NuGet packages for code that needs a deliberate published-version boundary.
Summary
- NuGet dependencies are declared per project, even inside one solution.
- Use
PackageReferencefor modern .NET package management. - Use
Directory.Packages.propsto centralize package versions across projects. - Use
ProjectReferencefor projects that are built together in the same solution. - Pack a project as a NuGet package only when you need a published artifact for external consumption.
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.