NET Core CLI - Create/update/modify/build and package a new project/solution
Orestis Meikopoulos
Head of Engineering | Cultivating Technical Leadership | C# & .NET Content Creator | Public Speaker
In today's article we are going to continue our exploration on .NET core concepts. As we already mentioned in our previous article, NET Core comes with a cross platform CLI, which is a command-line interface (CLI) tool used for developing, building, running, and publishing .NET Core applications. The .NET Core CLI is included with the .NET Core SDK. Installing only dotnet core runtime will not bring this tooling support into your development machine. Also, it is worth mentioning that, multiple dotnet CLI toolset versions can be installed side by side on your machine.
One of the best parts of .NET was Visual Studio, an IDE that allowed you to easily write code with code completion, easy debugging and packaging of your apps. Years later, .NET Core came into play and with it, the ability to use .NET cross-platform and with a very capable CLI tool Using the old .NET you knew there was an msbuild command in the background, but you seldom needed to care, Visual Studio handled it all for you. Using .NET Core though you have the best of both worlds, still the first-class experience of either Visual Studio or Visual Studio Code and with the CLI tool we have a first-rate terminal experience as well.
Now you might ask, why even bother using terminal commands, when I have pretty powerful IDEs that do all the job for me? Some of the strongest reasons, would include the following:
Command Structure
A .NET Core CLI command consists of the following components:
You see this pattern in most CLI operations, such as creating a new console app and running it from the command line, as the following commands show when executed from a directory named my_app.
Driver
Let's drill down on the components of a CLI command one by one. The driver, as we already saw, is named dotnet and has two responsibilities:
To be able to run a framework-dependent app, we can specify the app after the driver, for example something like the following command: dotnet /path/to/my_app.dll. If we wanted to use a specific version of the .NET Core Runtime, we can also use the --fx-version <VERSION> option.
When we supply a command to the driver, dotnet.exe starts the CLI command execution process (e.g. dotnet build). First, the driver determines the version of the SDK to use. If there is no global.json file, the latest version of the SDK available is used and it might be either a preview or a stable version, depending on what is latest on the machine. Finally, once the SDK version is determined, it executes the command.
The global.json file allows us to define which .NET Core SDK version is used when we run .NET Core CLI commands. Selecting the .NET Core SDK is independent from specifying the runtime our project targets. As a rule of thumb, we usually want to use the latest version of the SDK tools, so no global.json file is needed. NET Core SDK looks for a global.json file in the current working directory or one of its parent directories.
Command
The command performs an action. For example:
The commands are implemented as a console application using a dotnet {command} convention.
Arguments & Options
The arguments you pass on the command line are the arguments provided as input to the command invoked. For example, when we execute dotnet publish my_app.csproj, the my_app.csproj argument indicates the project to publish and is passed as input to the publish command.
The options you pass on the command line are the options also provided as input to the command invoked. For example, when we execute dotnet publish --output /build_output, the --output option and its value are passed as input to the publish command.
Let's begin exploring various NET Core CLI commands one by one.
dotnet new
Creates a new project, configuration file, or solution based on the specified template. The command calls the template engine to create the artifacts on disk based on the specified template and options.
An example syntax:
dotnet restore
Restores the dependencies of a project. For example, suppose you have added NuGet packages to your solution. This automatically adds a reference to your project’s .csproj file. If you check out the project from GitHub those packages are not versioned and will need to be added to your project. Running restore at this point will fetch the packages from the NuGet repository.
The command can be run in two ways:
dotnet build
Builds a project and its dependencies into a set of binaries. If you are at the root directory and you have a solution, then it will build the whole solution. If you are in a specific project directory, then it will only build that project. The binaries include the project's code in Intermediate Language (IL) files with a .dll extension. Depending on the project type, other files may be included, such as:
For executable projects targeting versions earlier than .NET Core 3.0, library dependencies from NuGet are typically NOT copied to the output folder. With that in mind, the product of dotnet build isn't ready to be transferred to another machine to run.
On the other hand, for executable projects targeting .NET Core 3.0 and later, library dependencies are copied to the output folder. This means that if there isn't any other publish-specific logic, the build output should be deployable.
dotnet run
Provides a convenient option to run your application from the source code with one command. The command depends on the dotnet build command to build the code. Output files are written into the default location, which is bin/<configuration>/<target>. For example if you have a netcoreapp2.1 application and you type dotnet run, the output is placed in bin/Debug/netcoreapp2.1. Files are overwritten as needed and temporary files are placed in the obj directory.
If the project targets multiple frameworks, executing dotnet run results in an error unless the -f | --framework <FRAMEWORK> option is used to specify the framework. The dotnet run command is used in the context of projects, not built assemblies. If you're trying to run a framework-dependent application DLL instead, you must use dotnet without a command. For example, to run myapp.dll, use?dotnet myapp.dll.
Keep in mind, that it's not recommended to use dotnet run to run applications in production. Instead, you should create a deployment using the dotnet publish command and deploy the published output.
dotnet test
Used to execute unit tests in a given solution. The dotnet test command builds the solution and runs a test host application for each test project in the solution. The test host executes tests in the given project using a test framework, for example: MSTest, NUnit, or xUnit and reports the success or failure of each test. If all tests are successful, the test runner returns 0 as an exit code; otherwise if any test fails, it returns 1. For multi-targeted projects, tests are run for each targeted framework.
Test projects specify the test runner using an ordinary <PackageReference> element, as seen in the sample project file below. Where you see "Microsoft.NET.Test.Sdk" is the test host, "xunit" is the test framework and "xunit.runner.visualstudio" is a test adapter, which allows the xUnit framework to work with the test host.
dotnet pack
Builds the project and creates NuGet packages. The result of this command is a NuGet package (that is, a .nupkg file). NuGet dependencies of the packed project are added to the .nuspec file, so they're properly resolved when the package is installed.
dotnet clean
This command cleans the output of the previous build. This means it takes away both the contents of obj as well as bin folders.
dotnet sln
This is the command you use to manage your solution. A solution keeps track of many projects and it’s a great way of managing a group of different projects that logically belongs together to do things like building or maybe publish an executable.
To create a solution you just place yourself in a directory of your choosing and run the dotnet new sln command. For example running the below commands:
领英推荐
will create a hello.sln file inside a folder named hello.
To manage the solution you have the following commands at your disposal:
dotnet add/remove reference
The dotnet add reference command will add a reference from a project to another project. For example, you are currently developing the console project app and you want to add a reference to the project lib to app. You can do this in one of two ways:
The dotnet remove reference command removes the specified reference from our project respectively.
To list the references of your project you can use the dotnet list reference command.
dotnet add/remove package
The dotnet add package command allows us to add a package from NuGet by specifying it by name. For example, typing dotnet add package Newtonsoft.Json, will add Newtonsoft.Json package to our project. It will also run a dotnet restore command which will fetch the package from NuGet's repository.
The dotnet remove package command removes the specified package from our project respectively.
To list the packages of your project you can use the dotnet list package command.
dotnet publish
Publishes the application and its dependencies to a folder for deployment to a hosting system. It compiles the application, reads through its dependencies specified in the project file, and publishes the resulting set of files to a directory
The output includes the following assets:
The dotnet publish command's output is ready for deployment to a hosting system for execution. Depending on the type of deployment that the project specifies, the hosting system may or may not have the .NET Core shared runtime installed on it.
What does the above mean? Basically, there are 2 types of deployment:
Commands Summary
Demo
Ok enough with the theory, time to see a small demo. Let's follow some steps one by one and see the result of each NET Core CLI command we execute:
For anyone interested on playing with the dotnet core CLI commands, there is a lab exercise in this GitHub link. Just follow the instructions listed there and have fun!
That's all for today. Cheers!