Codectionary / Developer documentation / C#

NuGet packages in .NET projects

Learn what NuGet packages are, add a verified package, restore dependencies and inspect requested and resolved versions.

What NuGet adds to a .NET project

NuGet is the package manager for the .NET development ecosystem, not a feature unique to C#. A package is a versioned bundle of reusable code or tools. Projects written in other .NET languages can use packages too. The libraries already supplied by .NET are often enough; add a package when it provides a capability your project actually needs.

For an SDK-style C# project, a package reference in the .csproj names a direct dependency. A package may itself depend on other packages; NuGet resolves those transitive dependencies. You do not normally copy DLL files into Program.cs or check downloaded package contents into the source folder.

Add a package to a new console project

This example uses the .NET 10 SDK and Newtonsoft.Json 13.0.4, a stable version verified on NuGet Gallery for .NET 10 compatibility. Create a console project in a writable folder, enter that folder, and add the package. Run each command in order. The dotnet package add command writes a PackageReference to PackageDemo.csproj and restores its dependencies. A network connection to an enabled package source is needed if the package is not cached.

On .NET 9 or earlier, the equivalent add command is dotnet add package Newtonsoft.Json --version 13.0.4. The newer noun-first spelling shown below was introduced in .NET 10. Do not run both variants on the same example project.

Terminal — .NET 10 SDK

dotnet new console -n PackageDemo
cd PackageDemo
dotnet package add Newtonsoft.Json --version 13.0.4

PackageDemo.csproj — reference added by the command

<ItemGroup>
  <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>

Use the package in Program.cs

Replace the template Program.cs with the example below and run dotnet run. The using line makes JsonConvert available without writing its full namespace. The anonymous learner object has Name and Level properties. SerializeObject turns it into JSON text, and Console.WriteLine displays that text in the terminal.

Expected output is {"Name":"Sam","Level":1}. This example teaches package use; modern .NET also has built-in System.Text.Json for many JSON tasks, so adding Newtonsoft.Json is not mandatory for every project. If the compiler cannot find Newtonsoft.Json, confirm the command changed this project’s .csproj and that restore succeeded.

Program.cs

using Newtonsoft.Json;

var learner = new { Name = "Sam", Level = 1 };
string json = JsonConvert.SerializeObject(learner);
Console.WriteLine(json);

Terminal — build and run

dotnet run

Restore declared dependencies

Restore reads the project’s package references, resolves compatible versions and makes the packages available to the build. Adding a package already triggers restore. dotnet build and dotnet run also normally restore when needed, so you do not have to run an extra command after every edit.

Run dotnet restore explicitly after cloning a project, changing package references manually or diagnosing a missing package. Restore does not add a new dependency to the project; it retrieves the dependencies already declared. If it fails, check your network, configured package sources and the package ID or version before changing code.

Terminal — inside the project folder

dotnet restore

Requested and resolved versions

A package has an ID and a version. Versions often use major.minor.patch numbers, and a suffix such as -beta marks a prerelease. The 13.0.4 example chooses a known stable release so everyone following the guide requests the same baseline; it is not a claim that 13.0.4 will always be the newest version. Check the package’s NuGet Gallery page for current compatibility, release information, dependencies, licence and advisories before adopting it.

A plain PackageReference Version="13.0.4" is interpreted by NuGet as a minimum acceptable version, not a strict lock to exactly 13.0.4 in every dependency graph. The package list command shows the requested and actually resolved version. Exact version ranges and lock files exist for stricter repeatability, but are beyond this first exercise. Update dependencies deliberately and retest your app rather than changing version numbers blindly.

Inspect what the project uses

In the project folder, dotnet package list shows direct package references with Requested and Resolved version columns. --include-transitive includes packages brought in by other packages. --outdated checks whether newer versions are available; it does not change them. The NuGet Gallery page for the package provides its description, supported frameworks, dependencies, owner information and licence.

These noun-first list commands use the .NET 10 SDK. With .NET 9 or earlier use dotnet list package and the same relevant options. If there is more than one project or solution in a folder, specify the project path rather than assuming the command will choose the intended one.

Terminal — inspect this project with .NET 10

dotnet package list
dotnet package list --include-transitive
dotnet package list --outdated

Common package problems

“Package not found” can mean the ID is misspelled, the selected source is unavailable, or the version does not exist. A compatibility warning means the package may not support the project’s target framework; check the Gallery compatibility table rather than suppressing it. A restore failure may be caused by a network, authentication or source configuration problem, not faulty C# syntax.

If the app compiles but the output is different, inspect the resolved version and read the package API documentation. Review package licences and security notices before adopting a dependency, particularly in a larger or commercial project. A package is third-party code that you must maintain as your app evolves.

Syntax

dotnet package add Newtonsoft.Json --version 13.0.4

Examples

Serialize a learner with Newtonsoft.Json

Add Newtonsoft.Json 13.0.4 to a .NET 10 console project before running this Program.cs.

using Newtonsoft.Json;

var learner = new { Name = "Sam", Level = 1 };
string json = JsonConvert.SerializeObject(learner);
Console.WriteLine(json);
  1. After dotnet package add Newtonsoft.Json --version 13.0.4 and a successful restore, save this as Program.cs and run dotnet run in PackageDemo. The output is {"Name":"Sam","Level":1}.
  2. using Newtonsoft.Json imports the package namespace. The anonymous object stores two named values. JsonConvert.SerializeObject converts those values to JSON text.
  3. Console.WriteLine prints the resulting string. In a real app, JSON might be sent to an API or saved to a file; this example prints it so you can verify what the package produced.

Best practices

  • Use packages only when they solve a real need; check the built-in .NET libraries first.
  • Inspect package versions, licences, target-framework compatibility and advisories before adoption.
  • Keep package references in the project file and restore them on another machine.
  • Compare requested and resolved versions before changing a dependency.

Runtime & versions

.NET runtime. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

C# language reference

Specifications & further reading