Free Ebook cover C# Essentials: Building Console Apps with .NET

C# Essentials: Building Console Apps with .NET

New course

12 pages

Using NuGet Packages in a Console App

Capítulo 10

Estimated reading time: 6 minutes

+ Exercise

What NuGet Provides

NuGet is the package manager for .NET. It lets you add third-party libraries (and Microsoft libraries that ship as packages) to your project in a repeatable way. A NuGet package typically contains compiled assemblies, metadata (package id, version, dependencies), and sometimes extra build assets (analyzers, MSBuild targets).

When you reference a package, your project records that dependency (including its version). During restore/build, NuGet resolves the full dependency graph (your direct packages plus their dependencies) and makes the assemblies available to the compiler and runtime.

Responsible Use of Third-Party Libraries

  • Prefer well-maintained packages with clear documentation and active releases.
  • Minimize dependencies: add packages only when they provide clear value.
  • Review licensing and security posture (known vulnerabilities, maintenance status).
  • Pin versions intentionally and update regularly, especially for security fixes.

Adding Packages with dotnet add package

To add a NuGet package to a console app, use the .NET CLI from the project folder (where the .csproj file is located). In this chapter’s example, you will use System.Text.Json for JSON serialization. It is a widely used JSON library in .NET and is distributed as a NuGet package (even though it is also part of many .NET shared frameworks).

Step-by-step: Add the package

dotnet add package System.Text.Json

This command updates your project file by adding a PackageReference. You can open the .csproj to see something like:

<ItemGroup>  <PackageReference Include="System.Text.Json" Version="8.0.0" /></ItemGroup>

The exact version may differ depending on your SDK and what NuGet resolves.

Continue in our app.

You can listen to the audiobook with the screen off, receive a free certificate for this course, and also have access to 5,000 other free online courses.

Or continue reading below...
Download App

Download the app

Restoring Dependencies

Restore is the process of downloading packages and resolving the dependency graph. Many CLI commands implicitly restore (such as dotnet build and dotnet run), but it is useful to know the explicit command.

Step-by-step: Restore

dotnet restore

Restore uses the package references in your project file to download packages into the global NuGet cache. It also generates a lock of resolved versions for the build (recorded in assets files under obj), ensuring your compiler sees the correct assemblies.

If restore fails, common causes include network issues, an invalid package id/version, or a restricted package source configuration.

Referencing Package APIs in Code

After adding a package, you can use its namespaces and types in your code. In practice, that means adding using directives and calling APIs as you would with any other library.

For JSON serialization with System.Text.Json, the main entry point is JsonSerializer in the System.Text.Json namespace.

Hands-on Example: Serialize to JSON, Save to a File, Read and Deserialize

This example creates a small data model, serializes it to JSON, writes it to a file, then reads it back and deserializes it into an object. The goal is to practice the full workflow: add package, restore, reference the API, and use it for a real task.

1) Create a simple model

Add a model type that represents something you might store locally, such as app settings or a user profile.

public class UserProfile{    public string UserName { get; set; } = "";    public int HighScore { get; set; }    public string[] FavoriteTags { get; set; } = Array.Empty<string>();}

2) Serialize the model to JSON

Create an instance and serialize it. Use JsonSerializerOptions to make the output readable (indented). In real apps, you might also configure naming policies or converters.

using System.Text.Json;public class Program{    public static void Main()    {        var profile = new UserProfile        {            UserName = "alex",            HighScore = 4200,            FavoriteTags = new[] { "console", "csharp", "json" }        };        var options = new JsonSerializerOptions        {            WriteIndented = true        };        string json = JsonSerializer.Serialize(profile, options);        Console.WriteLine(json);    }}

3) Save the JSON to a file

Pick a file path (for example, in the current working directory) and write the JSON string.

using System.Text.Json;public class Program{    public static void Main()    {        var profile = new UserProfile        {            UserName = "alex",            HighScore = 4200,            FavoriteTags = new[] { "console", "csharp", "json" }        };        var options = new JsonSerializerOptions { WriteIndented = true };        string json = JsonSerializer.Serialize(profile, options);        string filePath = "userprofile.json";        File.WriteAllText(filePath, json);        Console.WriteLine($"Saved JSON to {filePath}");    }}

4) Read the file and deserialize back into an object

Read the JSON text and deserialize it into UserProfile. The generic overload Deserialize<T> is the most common approach.

using System.Text.Json;public class Program{    public static void Main()    {        string filePath = "userprofile.json";        string jsonFromFile = File.ReadAllText(filePath);        UserProfile? loaded = JsonSerializer.Deserialize<UserProfile>(jsonFromFile);        if (loaded is null)        {            Console.WriteLine("Failed to load profile.");            return;        }        Console.WriteLine("Loaded profile:");        Console.WriteLine($"UserName: {loaded.UserName}");        Console.WriteLine($"HighScore: {loaded.HighScore}");        Console.WriteLine($"Tags: {string.Join(", ", loaded.FavoriteTags)}");    }}

5) Put it together as a single runnable program

This combined version writes the file and then reads it back in the same run, which is convenient for testing.

using System.Text.Json;public class UserProfile{    public string UserName { get; set; } = "";    public int HighScore { get; set; }    public string[] FavoriteTags { get; set; } = Array.Empty<string>();}public class Program{    public static void Main()    {        var profile = new UserProfile        {            UserName = "alex",            HighScore = 4200,            FavoriteTags = new[] { "console", "csharp", "json" }        };        var options = new JsonSerializerOptions { WriteIndented = true };        string filePath = "userprofile.json";        string json = JsonSerializer.Serialize(profile, options);        File.WriteAllText(filePath, json);        string jsonFromFile = File.ReadAllText(filePath);        UserProfile? loaded = JsonSerializer.Deserialize<UserProfile>(jsonFromFile);        if (loaded is null)        {            Console.WriteLine("Failed to deserialize JSON into UserProfile.");            return;        }        Console.WriteLine($"Loaded {loaded.UserName} with score {loaded.HighScore}.");    }}

If you get a deserialization result of null, it usually means the JSON is empty, malformed, or does not match the expected shape. Another common issue is mismatched property names when using custom naming policies.

Dependency Considerations: Versioning and Documentation

Versioning basics

NuGet packages use versions like Major.Minor.Patch. As a rule of thumb:

  • Patch updates should be backward compatible and include bug fixes.
  • Minor updates typically add features but should remain backward compatible.
  • Major updates may include breaking changes and require code updates.

You can specify a version when adding a package:

dotnet add package System.Text.Json --version 8.0.0

When you update packages, test your app after changes. Even “safe” updates can introduce behavior differences (for example, changes in default serialization behavior or stricter parsing).

Finding package documentation

  • Check the package page on NuGet.org for the README, release notes, and repository link.
  • Follow the repository link (often GitHub) for detailed docs, samples, and issue tracking.
  • Use the API reference (Microsoft Learn for BCL packages like System.Text.Json, or the library’s own docs for third-party packages).

Now answer the exercise about the content:

After adding a NuGet package to a console app, what does the restore/build process do with that package reference?

You are right! Congratulations, now go to the next page

You missed! Try again.

When a package is referenced, the project records the dependency and version. During restore/build, NuGet resolves all dependencies and provides the assemblies needed for compilation and execution.

Next chapter

Reading .NET API Documentation and Applying It in Code

Arrow Right Icon
Download the app to earn free Certification and listen to the courses in the background, even with the screen off.