How To Create A dotnet new Project Template In .NET Core

Being this blog post was created using a VS 2017 RC, things are bound to change over time. I will do my best to keep this post up-to-date as we get closer to a GA/RTM release of VS 2017.

March 7th, 2017 is just around the corner and with it comes the general availability of Visual Studio 2017. Those who have been exploring the RC builds might have noticed a slew of updates coming to the dotnet new command in the dotnet cli. One such feature now allows us to create project templates that can be installed from a NuGet package or local folder.

I will use the Pioneer Console Boilerplate project I created to demonstrate the concepts of "Dependency Injection, Logging and Configuration In A .NET Core Console Application" to show the following.

  1. Migrating project.json to the new .csproj build config required in VS 2017.
  2. Create necessary config to allow your project to serve as a template.
  3. Installing your template from a local folder.
  4. Removing your template.
  5. Publishing and installing from Nuget.

That being said, it is worth mentioning that there is zero reason as to why this would not work in an ASP.Net project. Templating is universal to .NET Core.

Migrating project.json

In an effort to simplify compatibility with MSBuild, project.json is being retired in favor of .csproj. The process, in most cases, is dirt simple. You have one of two options, run dotnet migrate or automation provided by Visual Studio 2017. For this project, I choose to have Visual Studio guide me through the process.

When I opened up Pioneer Console Boilerplate in VS 17, I was prompted with the following.

Migration Prompt

After confirming by clicking OK, I was supplied with the following report.

Migration Report

Everything is pretty self-explanatory. A backup was made of all files being touched prior to migration, followed by the actual migration taking place. Below is a view of the original project.json and the new Pioneer.Console.Boilerplate.csproj files side by side for comparison.

Side by side comparison.

Adding Template Configuration

At the time a wrote this blog, details on the dotnet new templating system are understandable lacking. After all, I am doing this in an RC of VS 17. The information I was able to gather came from one of three sources.

  1. The official documentation.
  2. A project that has the templating system already figure out.
  3. Going straight to the source and asking Sayed I. Hashimi on twitter.

Let's start by creating a folder called .template.config in the project you want make a template. Inside that folder, add a file called template.json.

Template Solution View

There is a pretty long list of configuration options that can go into your template.json file. For more information, I recommend going to official documentation. Below is what I have added to my configuration, mostly consisting of required fields.

{
  "author": "Chad Ramos <[email protected]>",
  "classifications": [ "Console", "Boilerplate", "Dependency Injection", "Logging", "Configuration" ],
  "name": "Pioneer Code: Console Application with dependency injection, logging & configuration.",
  "tags": {
    "language": "C#"
  },
  "identity": "Pioneer.Console.Boilerplate",
  "shortName": "consoleboilerplate",
  "sourceName": "Pioneer.Console.Boilerplate"
}

Installing Your Template From a Local Folder

To install your project as a template from your local folder, run the following - dotnet new --install C:\source\Repos\pioneer-console-boilerplate\Pioneer.Console.Boilerplate. You will need to adjust the path to your project as needed.

Once installed, you should see your template in the available list. Run dotnet new -l to list all templates available.

Dot Net new list.

To use your new template to generate a project, run the following command with appropriate Short Name and project name to output with, dotnet new consoleboilerplate -n my.console. You should now see your new project in the directory specified.

New Project.

Where Does Your New Template Cache Live?

This section only exists because I was curious. At this point, I would not recommend manually editing these files.

By running the dotnet new -i [source] command, you are telling the cli to cache a reference to your package configuration. The dotnetcli needs to store this information in order to display your templates information when running dotnet new. That being the case, I started searching around my local directories to find the file(s) holding this information.

Navigate to C:\Users\vagrant\.templateengine\dotnetcli\v1.0.0-rc4-004771. You will obviously have to update the user and version to suite your needs. In this folder there are few files, templatecache.json, settings.json & en-us.templatecache.json. Each of held a reference to my local template.

Template cache

Side note, after manually deleting the references to my template from these files, dotnet new -l no longer had a reference to my template.

Empty List

Removing your template

Fair warning, being I can't find documentation on the reinit flag I can only assume that you will lose all configuration you have done to your environment if it is ran.

At the moment there is no syntax to remove a single template. Though, it appears to be coming soon. That being said, you can run dotnet new --debug:reinit to re-initialize your environment. Of which will effectively remove any new templates you added.

Tweet

Creating A NuGet Package To Serve Our Template.

What if we want to serve up our template through a NuGet package? Lucky for us, the process is pretty straight forward.

Creating A nuspec file

For a full reference of possible configuration, you can visit the official Creating A Package documentation. At the date of this publishing, V4.0 of nuget.exe was still a RC. That being said, the packageTypes node was not yet documented because it is new to V4.0.

We need to first create a manifest that describes our package. This file in the NuGet world is refereed to as a nuspec file. That being said, let's start out by creating a file called Templates.nuspec and place it at the root of your project for the time being.

I added the following to my file.

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
    <metadata>
        <id>Pioneer.Console.Boilerplate</id>
        <version>0.1.0</version>
        <description>Pioneer Code: .NET Core Console Application with dependecy injection, logging &amp; configuration</description>
        <authors>Chad Ramos ([email protected])</authors>
        <language>en-US</language>
        <projectUrl>https://github.com/PioneerCode/pioneer-console-boilerplate</projectUrl>
        <licenseUrl>https://github.com/PioneerCode/pioneer-console-boilerplate/blob/master/LICENSE</licenseUrl>
        <copyright>Copyright 2017: Chad Ramos - Pioneer Code. All right Reserved.</copyright>
        <requireLicenseAcceptance>true</requireLicenseAcceptance>
        <packageTypes>
            <packageType name="Template" />
        </packageTypes>
    </metadata>
</package>>

Reorganizing Our Project

The contract that NuGet defines is for your nuspec file to live by a folder called content. The content folder will house the static files that make up your template. With that in mind, I decided to nest my project code one level deeper to facilitate this. Make note that you will have to move your nuspec file out of your project source folder.

Nuspec Contract Nuspec Content

Building A Package

According to the Nuget Distributions page, NuGet 4.x is included in the Visual Studio 2017 installation. With my current VS 2017 RC install, I could not find the executable and ended up downloading it directly from the link I just provided.

Typically you would be able to reference nuget directly on the command line by scoping to the directory your nuget.exe is installed or by adding a PATH variable to your environment. In my case I chose to temporary move the nuget.exe I downloaded to the directory my nuspec file lived.

I trust on a fresh install of VS 17 GA/RTM, the nuget.exe will be available.

Now that we have our nuspec file created and our static content in the appropriate folder, let's go ahead and create our package by running the following command, nuget pack. You should end up with a file that with the following structure, [id][version].nupkg. The id and version variables come directly from your nuspec configuration.

.nupkg can be extracted with a zip client. I used 7-Zip to peek into my package and verify the contents of the Content folder.

Publishing A Package

This is a topic that is out of the scope of this blog post. In short, I did the following.

  1. Create a new account at nuget.org
  2. Used the Upload Package dashboard to verify and upload my package.

My package was then made available at Pioneer.Console.Boilerplate.

For more information on how to publish your package, head over to the official Creating A Package documentation.

Consuming Your Package

Now that your package is available from the NuGet repository, you can install your template directly from your new feed.

After running dotnet new -i Pioneer.Console.Boilerplate::*, I ended up with the following.

Dot Net new list.

In regards to the Pioneer.Console.Boilerplate::* portion of that command, the asterisk signifies "I want the latest version". I could have targeted a specific version using something like Pioneer.Console.Boilerplate::0.1.0

As of the date this was posted, the syntax for install a nuget package is as follows dotnet new --install [name]::[version]. In the very near future this will change to dotnet new --version [name]::[version]. For more information, you can check out the open issue at GitHub

Dot Net new version.

At this point, you can again install your template by running the following command with appropriate Short Name and project name to output with, dotnet new consoleboilerplate -n my.console.

That is that. Though there are still some challenges to overcome with dotnet new templating being new and all, the future looks very bright. As always, let me know your thoughts below in the comments section.