.NET Core solution management via the command line interface

Posted on Monday, 03 Jul 2017

One of the strengths boasted by .NET Core is its new command line interface (CLI for short), and by now you're probably aware that Visual Studio, Rider, Visual Studio Code etc shell out to the .NET Core CLI under the bonnet for most .NET Core related operations, so it makes sense that what you're able to do in your favourite IDE you're also able to do via the CLI.

With this in mind, only recently did I spend the time and effort to investigate how easy it was to create and manage a project solution via the CLI, including creating the solution structure, referencing projects along the way and adding them to .NET's .sln file.

It turns out it's incredibly easy and has instantly become my preferred way of managing solutions. Hopefully by the end of this post you'll arrive at the same conclusion too.

Benefits of using the CLI for solution management

So what are the benefits of using the CLI for solution management? Let's have a look:

  • Something that has always been a fiddly endevour of UI interactions is now so much simpler via the CLI - what's more, you don't need to open your editor of choice if you want to create references or update a NuGet package.

  • Using the CLI for creating projects and solutions is particularly helpful if (like me) you work across multiple operating systems and want to normalise your tool chain.

  • Loading an IDE just to update a NuGet package seems unnecessary

Let's begin!

Creating our solution

So let's take a look at how we can create the following project structure using the .NET Core CLI.

piedpiper
└── src
    ├── piedpiper.domain
    ├── piedpiper.sln
    ├── piedpiper.tests
    └── piedpiper.website

First we'll create our solution (.sln) file, I've always preferred to create the solution file in the top level source folder but the choice is yours (just bear in mind to specify the right path in the commands used throughout the rest of this post).

# /src/

$ dotnet new sln -n piedpiper

This will create a new sln file called piedpiper.sln.

Next we use the output parameter on the dotnet new <projecttype> command to create a project in a particular folder:

# /src/

$ dotnet new mvc -o piedpiper.website

This will create an ASP.NET Core MVC application in the piedpiper.website folder in the same directory. If we were to look at our folder structure thus far it looks like this:

# /src/

$ ls -la

piedpiper.sln
piedpiper.website

Next we can do the same for our domain and test projects:

# /src/

$ dotnet new classlib -o piedpiper.domain
$ dotnet new xunit -o piedpiper.tests

Adding our projects to our solution

At this point we've got a solution file that has no projects referenced, we can verify this by calling the list command like so:

# /src/

$ dotnet sln list

No projects found in the solution.

Next we'll add our projects to our solution file. Once upon a time doing this involved opening Visual Studio then adding a reference to each project manually. Thankfully this can also be done via the .NET Core CLI.

Now start to add each project with the following command, we do this by referencing the .csproj file:

# /src/

$ dotnet sln add piedpiper.website/piedpiper.website.csproj
$ dotnet sln add piedpiper.domain/piedpiper.domain.csproj
$ dotnet sln add piedpiper.tests/piedpiper.tests.csproj

Note: If you're using a Linux/Unix based shell you can do this in a single command using a globbing pattern!

# /src/

$ dotnet sln add **/*.csproj

Project `piedpiper.domain/piedpiper.domain.csproj` added to the solution.
Project `piedpiper.tests/piedpiper.tests.csproj` added to the solution.
Project `piedpiper.website/piedpiper.website.csproj` added to the solution.

Now when we call list on our solution file we should get the following output:

# /src/

$ dotnet sln list

Project reference(s)
--------------------
piedpiper.domain/piedpiper.domain.csproj
piedpiper.tests/piedpiper.tests.csproj
piedpiper.website/piedpiper.website.csproj

So far so good!

Adding a project reference to a project

Next up we want to start adding project references to our project, linking our domain library to our website and test library via the dotnet add reference command:

# /src/

$ dotnet add piedpiper.tests reference piedpiper.domain/piedpiper.domain.csproj

Reference `..\piedpiper.domain\piedpiper.domain.csproj` added to the project.

Now if you were to view the contents of your test project we'd see our domain library has now been referenced:

# /src/piedpiper.tests/

$ cat piedpiper.tests/piedpiper.tests.csproj 

<Project Sdk="Microsoft.NET.Sdk">

  ...

  <ItemGroup>
    <ProjectReference Include="..\piedpiper.domain\piedpiper.domain.csproj" />
  </ItemGroup>

</Project>

Next we'll do the same for our website project, so let's go to our website folder and run the same command:

# /src/

$ dotnet add piedpiper.website reference piedpiper.domain/piedpiper.domain.csproj
# /src/

$ cat piedpiper.website/piedpiper.website.csproj 

<Project Sdk="Microsoft.NET.Sdk">

  ...

<ItemGroup>
    <ProjectReference Include="..\piedpiper.domain\piedpiper.domain.csproj" />
  </ItemGroup>

</Project>

At this point we're done!

If we navigate back to our root source folder and run the build command we should see everything build successfully:

$ cd ../

# /src/

$ dotnet build

icrosoft (R) Build Engine version 15.3.388.41745 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

    piedpiper.domain -> /Users/josephwoodward/Desktop/demo/src/piedpiper.domain/bin/Debug/netstandard2.0/piedpiper.domain.dll
    piedpiper.tests -> /Users/josephwoodward/Desktop/demo/src/piedpiper.tests/bin/Debug/netcoreapp2.0/piedpiper.tests.dll
    piedpiper.website -> /Users/josephwoodward/Desktop/demo/src/piedpiper.website/bin/Debug/netcoreapp2.0/piedpiper.website.dll

Build succeeded.

    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:08.08

Adding a NuGet package to a project or updating it

Before wrapping up, let's say we wanted to add a NuGet package to one of our projects, we can do this using the add package command.

First navigate to the project you want to add a NuGet package to:

# /src/

$ cd pipedpiper.tests/

$ dotnet add package shouldly

info : Adding PackageReference for package 'shouldly'
...
log  : Installing Shouldly 2.8.3.

Optionally we could specify a version we'd like to install using the version argument:

$ dotnet add package shouldly -v 2.8.2

Updating a NuGet package

Updating a NuGet package to the latest version is just as easy, simply use the same command without the version argument:

dotnet add package shouldly

Conclusion

If you've managed to get this far then well done, hopefully by now you've realised how easy creating and managing a solution is using the new .NET Core command line interface.

One of the great powers of using the CLI is you can now turn creating the same project structure into a handy bash script which you could alias and reuse!

#!/bin/bash

echo "Enter project name, followed by [ENTER]:"
read projname

echo "Creating solution for $projname"

dotnet new sln -n $projname

dotnet new mvc -o $projname.website
dotnet new classlib -o $projname.domain
dotnet new xunit -o $projname.tests

echo "Adding projects to solution"
dotnet sln add **/*.csproj

echo "Referencing projects"
dotnet add $projname.website reference $projname.domain/$projname.domain.csproj
dotnet add $projname.tests reference $projname.domain/$projname.domain.csproj

Happy coding!

Back