How do I determine the dependencies of a .NET application?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
When a .NET application behaves differently after build or deployment, the problem is often a dependency issue rather than a code bug. The useful way to inspect dependencies is to look at three layers separately: what the project declares, what NuGet resolves, and what the published app actually carries at runtime.
Start with the project file
The .csproj file shows direct dependencies explicitly. In modern SDK-style projects, you will usually see PackageReference and ProjectReference entries.
This tells you what your application asked for directly, but not everything it ended up with. For transitive dependencies, you need the CLI.
Use the dotnet CLI to see resolved packages
The most useful first command is:
That shows direct NuGet package references. To include transitive packages as well:
This is often the fastest way to answer questions such as:
- which package pulled in a particular library
- why a certain version appeared in restore output
- whether two projects are resolving different versions of the same package
For application behavior, run this command against the executable project, not just a class library.
Inspect the publish output
Project and restore information are useful, but the publish output is what the runtime actually uses. Publish the app first:
A published app usually includes files such as:
- '
MyApp.dll' - '
MyApp.runtimeconfig.json' - '
MyApp.deps.json'
The .deps.json file is especially important because it records runtime dependency information for the published application.
If you want a quick look at that manifest, open it directly or use a JSON tool:
That helps answer the question "what does the runtime expect to be present" rather than only "what did the project file declare."
Use the right layer for the question
A useful rule is:
- '
.csprojanswers what you declared directly' - '
dotnet list package --include-transitiveanswers what NuGet resolved' - '
.deps.jsonanswers what the published runtime expects'
These are related but not identical views. A package can be restored without contributing a runtime assembly. A project reference can exist only for tests. A target framework condition can change which dependencies appear in output.
That is why dependency debugging gets easier when you stop asking one tool to answer every question.
When dependency graphs get complicated
If package resolution is still unclear, generate a restore graph:
This produces a verbose graph file that is useful when central package management, target framework conditions, or version conflicts make the simpler commands insufficient.
You can also inspect assemblies with tools such as ILSpy if the real question is about assembly references rather than NuGet packages.
Common Pitfalls
The biggest pitfall is checking only the project file and assuming that tells the whole story. It does not reveal transitive dependencies or runtime asset selection.
Another issue is inspecting a library project when the deployment problem belongs to the app project. The executable entry point is the better source of truth for runtime behavior.
It is also easy to forget target frameworks and build configurations. The dependency set for net8.0 Debug may not match what gets published for Release or for a different target framework.
Finally, do not confuse packages with output files. A package may contain assemblies, native assets, analyzers, or build targets, and not all of those end up beside the executable.
Summary
- Check the
.csprojfile for direct package and project references. - Use
dotnet list package --include-transitiveto inspect the resolved package graph. - Inspect
.deps.jsonin publish output to see runtime dependencies. - Generate a restore graph when version resolution is still unclear.
- Investigate the executable project and exact target framework you actually deploy.

