Skip to content

Building a Solution with dotnet cli templates

2017-02-20

In a previous post I showed an example of using dotnet cli commands to create a sample web solution with a web project that has dependencies on models and services projects and a test project that also is in the mix. I personally think that is super useful and I can think of scenarios where I will be using that. Another scenario is where you have a project starting and you already know how you want your project setup.

Let's take the previous post's setup and the starting point for the template feature in the new dotnet cli. The structure for that project was as follows:

- SampleApp
  - Models/
  - Services/
  - Services.Test/
  - Web/
  SampleApp.sln

It would be nice to be able to have a simple command handy for the team or a project bootstrapper to get thing started. The team behind the dotnet cli made this pretty easy by just adding an additional .template.config directory and a template.json file within that directory you can have a template sitting on the file system that allows you do create an entire project structure in one shot.

- mytemplate
  - .template.config/
     - template.json
  - Models/
  - Services/
  - Services.Test/
  - Web/
  mytemplate.sln

In this example my template.json file has the following

{
  "author": "Some Author",
  "classifications": ["mytemplate"],
  "name": "mytemplate",
  "identity": "mytemplate",
  "shortName": "mytemplate",
  "tags": {
    "language": "C#",
    "type": "solution"
  },
  "sourceName": "mytemplate"
}
Here in the interesting bit is in the sourceName attribute. For my simple example when the template is initiated and your project is created it will use the supplied --name value to, in this case, name the solution file your supplied value.

For example, dotnet new mytemplate -all --name sampleapp --output sampleapp-location would create a solution called sampleapp.sln based on the name value and drop it into a directory called sampleapp-location

After you have the file system based template created in a well-known location you need to tell the dotnet cli about it by installing it with dotnet new -i path/to/your/template/root. Make sure it was installed correctly by calling the list command with and you should see your template along side the shipping templates with dotnet new --list -all.

Templates                             Short Name   Language  Tags
---------------------------------------------------------------------------
Console Application                   console      [C#], F#  Common/Console
Class library                         classlib     [C#], F#  Common/Library
Unit Test Project                     mstest       [C#], F#  Test/MSTest
xUnit Test Project                    xunit        [C#], F#  Test/xUnit
Empty ASP.NET Core Web Application    web          [C#]      Web/Empty
MVC ASP.NET Core Web Application      mvc          [C#], F#  Web/MVC
Web API ASP.NET Core Web Application  webapi       [C#]      Web/WebAPI
mytemplate                            mytemplate   [C#]      mytemplate
Nuget Config                          nugetconfig            Config
Web Config                            webconfig              Config
Solution File                         sln                    Solution

I wrapped some of this up in a variation of the previous script.

Param(
    [string] [Parameter(Mandatory=$true)] $SolutionName,
    [ValidateSet('netcoreapp1.0','netcoreapp1.1')]
    [string] $framework = "netcoreapp1.1"
)

# Create source directory and change directory to it
New-Item -ItemType Directory -Path $SolutionName | Out-Null

# Set some defaults names & paths
$webProject = "Web"
$modelsProject = "Models"
$servicesProject = "Services"
$servicesTestProject = "$servicesProject.Tests"

$webProjectPath = "$webProject\$webProject.csproj"
$modelsProjectPath = "$modelsProject\$modelsProject.csproj"
$servicesProjectPath = "$servicesProject\$servicesProject.csproj"
$servicesTestProjectPath = "$servicesTestProject\$servicesTestProject.csproj"

#Create all of our individual projects
dotnet new mvc --name $webProject --output $SolutionName\$webProject --framework $framework 
dotnet new classlib --name $modelsProject --output $SolutionName\$modelsProject --framework $framework
dotnet new classlib --name $servicesProject --output $SolutionName\$servicesProject --framework $framework
dotnet new xunit --name $servicesTestProject --output $SolutionName\$servicesTestProject --framework $framework

#Add all of our individual projects to the solution
dotnet new sln --name $SolutionName --output $SolutionName
$solutionPath = ".\$solutionName\$SolutionName.sln"
dotnet sln $solutionPath add .\$SolutionName\$webProjectPath
dotnet sln $solutionPath add .\$SolutionName\$modelsProjectPath
dotnet sln $solutionPath add .\$SolutionName\$servicesProjectPath
dotnet sln $solutionPath add .\$SolutionName\$servicesTestProjectPath

# Add all the of the nessessary project references
dotnet add .\$SolutionName\$webProjectPath reference .\$SolutionName\$modelsProjectPath
dotnet add .\$SolutionName\$webProjectPath reference .\$SolutionName\$servicesProjectPath
dotnet add .\$SolutionName\$servicesProjectPath reference .\$SolutionName\$modelsProjectPath
dotnet add .\$SolutionName\$servicesTestProjectPath reference .\$SolutionName\$modelsProjectPath
dotnet add .\$SolutionName\$servicesTestProjectPath reference .\$SolutionName\$servicesProjectPath

New-Item -ItemType Directory -Path "$SolutionName\.template.config" | Out-Null

@"
{
  "author": "Some Author",
  "classifications": ["$SolutionName"],
  "name": "$SolutionName",
  "identity": "$SolutionName",
  "shortName": "$SolutionName",
  "tags": {
    "language": "C#",
    "type": "solution"
  },
  "sourceName": "$SolutionName"
}
"@ | Out-File -FilePath "$SolutionName\.template.config\template.json" -Encoding ascii

dotnet new -i .\$SolutionName
dotnet new --list -all

Silvrback blog image