The dotnet CLI and Solutions
Creating projects, adding packages from NuGet, formatting code, and grouping several projects into one solution.
dotnet package add <PACKAGE_NAME> [-v|--version <VERSION>]dotnet is one command with many subcommands, and they all arrive with the SDK. There is nothing extra to install.
Creating and referencing
dotnet new <template> creates a project from a template; dotnet new list prints the templates, among them console, classlib, webapi and xunit. dotnet package add <name> adds a package: a library someone else published. It writes a PackageReference line into the .csproj and then restores. Packages come from NuGet, the public .NET package gallery at nuget.org. .NET 10 documents the noun-first order, dotnet package add; the older dotnet add package still works and is what you will see in most existing scripts.
Where restored packages live
Restore downloads each package once into a shared folder, not into your project: ~/.nuget/packages on macOS and Linux, %userprofile%\.nuget\packages on Windows. dotnet nuget locals all --list prints the paths.
Solutions
A solution is a list of projects that belong together, so one command can build or test all of them. dotnet new sln -n Shop creates it and dotnet sln Shop.slnx add Api/Api.csproj adds a project.
Formatting
dotnet format rewrites your code to match the rules in an .editorconfig file. dotnet format --verify-no-changes edits nothing and exits with a failure code if any file would have changed, which is the form a build server should run.
Example
// Program.cs of the Api project, created and wired up with:
// dotnet new sln -n Shop
// dotnet new console -o Api
// dotnet sln Shop.slnx add Api/Api.csproj
// dotnet format Api/Api.csproj
//
// From the solution folder, this project is started with:
// dotnet run --project Api
Console.WriteLine("Api started.");
Console.WriteLine("Shop.slnx lists the projects that build together.");
// Output:
// Api started.
// Shop.slnx lists the projects that build together.When to use it
- Adding a database driver to a service and recording the version in source control.
- Grouping an API project, a shared library and a test project so one command builds all three.
- Failing a continuous integration build when code is not formatted, without changing the files.
- Finding where a restored package's files actually sit on disk.
More examples
A solution with two projects
This is the layout almost every real service grows into: an application project, one or more libraries, and a test project. A project reference is what lets Api use types written in Shop.Core.
dotnet new sln -n Shop # creates Shop.slnx on .NET 10 and later
dotnet new console -o Api # the service
dotnet new classlib -o Shop.Core # shared code, no entry point
dotnet sln Shop.slnx add Api/Api.csproj Shop.Core/Shop.Core.csproj
cd Api
dotnet add reference ../Shop.Core/Shop.Core.csproj
cd ..
dotnet build Shop.slnx # builds every project in the solution
dotnet sln Shop.slnx list # prints what is in itAdding a package and finding where it went
Use this whenever you need a library you did not write, such as a database driver. The listing matters during a disk-space or corrupted-cache investigation, because the packages are in that one shared folder and not inside your repository.
dotnet package add Npgsql
# Writes a <PackageReference Include="Npgsql" ... /> line into the .csproj
# and then restores the package.
# Pin an exact version when you need to:
# dotnet package add <name> --version <version>
dotnet package list # what this project references
dotnet nuget locals global-packages --list
# info : global-packages: /Users/you/.nuget/packages/Formatting, and checking formatting in CI
Run dotnet format before you commit, and --verify-no-changes in the pipeline. The second form is what keeps formatting arguments out of code review without a build step that quietly edits the repository.
dotnet new editorconfig # an .editorconfig with the .NET defaults
dotnet format # rewrite files to match it
# For a build server: changes nothing, fails if anything is unformatted.
dotnet format --verify-no-changes
Discussion