Today’s header image was created by Frank McKenna at Unsplash

I’ve talked about .NET Core’s shiny new templating system before, and even covered using their Angular template. But those were always making use of someone else’s template.

Recently I built and open sourced

because of course I did

my own .NET Core template, and in this article I’ll show you how I did it.

if you want to skip the whole article and get straight to the template, you can find it here


Template Creation

The boffins at Microsoft have realised that most of the templates that we need are built from pre-existing code bases.

perhaps your organisation or group has a pre-existing .NET Framework template? We can use that with .NET Core, but with a few tweaks.

This means that you can stub out the structure and workflow for most of your projects within the template before having others use it. Once you’ve done that, it’s a case of adding a file called template.config and running a console command.

It’s really quite simple, and if you follow along, you’ll see just how simple it is.

But first…

psst, if you want to skip directly to converting a solution to a template, click here

Introducing: FullStackTemplate

I’d noticed that I was spending time writing a lot of common, boilerplate code when setting up new solutions. So I decided to create my own template: FullStackTemplate

I started by looking at the common code and structure among all of my pre-existing solutions, extracting what was common. I then took a look at some suggested best practises for .NET Core application organisation.

“application organisation” is fun to say. Say it with me

Which lead me to a talk by K. Scott Allen (of OdeToCode) from this year’s NDC in London.

if you’re reading this in the future, “this year” is 2017

I’ll embed the full talk here:

He raises some very interesting points (and a few that you should be doing anyway, like bundling with WebPack)

hey, I’ve written about that before

The talk was given back before .NET Core 2.0 was in preview, but most of the points are still valid for .NET Core 2.0. It’s also an hour long, so it’ll take some time to sit through the whole thing, but it’s totally worth it. K. Scott Allen really knows his stuff and has a lot of useful advice.

If audio is more your thing, then I’d check out this episode of .NET Rocks!

I’d also really recommend .NET Rocks! as it’s a fantastic podcast

From that, I took some time to refactor my Startup class, add Feature folders and use Façades rather than mediators.

for a quick description of the difference between these patterns, take a look at this Stack Overflow answer

I also decided to target .NET Core 2.0, ASP.NET Core 2.0 and EF Core 2.0.

and all the other common libraries, at version 2.0

Before I talk about how to use the template, I thought I’d talk through it a little. So without further ado:

Startup class

if you want to skip straight to installing and using the template, click here

Taking details directly out of K. Scott Allen’s approach, I decided to clean up my Startup class by using extension methods.

Here’s the cleaned up (.NET Core 2.0 Startup class in my template):

using ClacksMiddleware.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace FullStackTemplate.UI
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext();
services.AddTransientServices();
services.AddFacades();
services.AddCustomizedMvc();
services.AddFeatureFolders();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.GnuTerryPratchett();
app.UseStaticFiles();
app.UseCustomisedMvc();
}
}
}

wait?! What’s GnuTerryPratchett? 

The highlighted lines show where I’ve leveraged extension methods to clear up the Startup class by implementing the Newpaper Metaphor.

Here’s a description of the Newspaper metaphor, taken from Mona’s Learning Blog:

code should read like a newspaper article. First the title, then the introduction, only later the details. Name should be simple but explanatory. The article should be short enough to make it attractive to read

source: “Clean Code” Robert C. Martin at Mona’s Learning Blog

if you’ve not read Clean Code but take your career seriously, then I’d recommend that you read it. And soon.

ConfigureServices

The ConfigureServices method in the Startup class is used to set up the container that our application will use, so the extension methods used in that method are found in the ConfigureContainerExtenstions.cs file. Here’s an example of one of the extension methods (this one adds the Façades):

/// <summary>
/// Adds all transient facades into .NET Core's Dependency Injection Service
/// </summary>
/// <param name="serviceCollection"></param>
public static void AddFacades(this IServiceCollection serviceCollection)
{
// TODO add more transient facades here
// Api Facades
serviceCollection.AddTransient<IBaseApiFacade, BaseApiFacade>();
serviceCollection.AddTransient<IDatabaseFacade, DatabaseFacade>();
// Feature Facades
serviceCollection.AddTransient<IHomeFacade, HomeFacade>();
}

Before we continue our look at the Startup class, let’s take a look at Feature Folders.

Feature Folders

Feature Folders are a great way to use MVC’s routing to collect as much of our MVC code together in single units.

as you’ll soon see, Feature Folders is a little like Areas

In traditional MVC, you might have something like the following:

Standard MVC Folder Layout
This is a really simple example, obviously.

In this example, if you want to add some new properties to a model, you need to visit:

  • The Models directory (to add the properties to the model)
  • The Controllers directory (to populate the new properties on the model)
  • The Views directory (to consume the new properties on the model)

And that’s assuming that you’re consuming the view model in one View.

I’ve seen the same view model being consumed across multiple different views (in different view directories) before

If all of the affected files are related to the same view, then why not have them collected together?

That’s where Feature Folders comes in.

I prefer “directory” over “folder”, but I’ll stick with folder for consistency

In Feature Folders we take all of the Controllers, Views and Models for a given feature (say, the Home pages) and put them into a single directory. An example of an MVC app using feature folders would be:

Features Directory Layout
Another really simple example.

This isn’t for everyone, but I really like this layout.

Back To The Startup Class

Taking a look at the AddFeatureFolders extension method:

/// <summary>
/// Adds rules to the <see cref="RazorViewEngineOptions"/> for dealing with Feature Folders
/// </summary>
/// <param name="serviceCollection">
/// The <see cref="IServiceCollection"/> created in <see cref="Startup.ConfigureServices"/>
/// </param>
public static void AddFeatureFolders(this IServiceCollection serviceCollection)
{
serviceCollection.Configure<RazorViewEngineOptions>(options =>
{
options.ViewLocationExpanders.Add(new FeatureLocationExpander());
});
}

Here I’m making use of the RazorViewEngineOptions class to set up ASP.NET Core’s view routing for our Feature Folders.

This is different from MVC routing. The list of view location expanders is what Razor uses to figure out out where to look for the controllers, views and models for our request.

I’m passing in the output of the FeatureLocationExpander class into the ViewLocationExpandersproperty on the RazorViewOptions class.

Here’s what the FeatureLocationExpander looks like:

using System.Collections.Generic;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc.Razor;
[assembly: AspMvcViewLocationFormat("~/Api/{1}{0}.cshtml")]
[assembly: AspMvcViewLocationFormat("~/Features/{1}/{0}.cshtml")]
[assembly: AspMvcViewLocationFormat("~/Features/Shared/{0}.cshtml")]
namespace FullStackTemplate.UI
{
/// <summary>
/// Used to apply Features directories (rather than separate Controller, Model
/// and View directories).
/// </summary>
/// <remarks>
/// See: https://scottsauber.com/2016/04/25/feature-folder-structure-in-asp-net-core/
/// </remarks>
public class FeatureLocationExpander : IViewLocationExpander
{
public void PopulateValues(ViewLocationExpanderContext context)
{
// Don't need anything here, but required by the interface
}
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
{
// The old locations are /Views/{1}/{0}.cshtml and /Views/Shared/{0}.cshtml
// where {1} is the controller and {0} is the name of the View
// Replace /Views with /Features
return new string[]
{
"/Api/{1}/{0}.cshtml",
"/Features/{1}/{0}.cshtml",
"/Features/Shared/{0}.cshtml"
};
}
}
}

The first highlighted section is a fix for ReSharper. Without this fix ReSharper, and by extension Rider

which I would recommend to anyone

would complain that the models, views and controllers could not be found. This isn’t required for .NET Core, but it’s nice to not have the dev tools complain at you.

The ExpandViewLocations method returns a list of places for ASP.NET Core’s view routing to look in order to build the responses to incoming requests.

i.e where the models, views and controllers are

Configure

The Configure method in the Startup class is used to set up the HTTP Pipeline that our application will use, so the extension methods used in that method are found in the ConfigureHttpPipelineExtentions.cs file. Let’s take another look at the contents of the Configure method in the Startup class:

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.GnuTerryPratchett();
app.UseStaticFiles();
app.UseCustomisedMvc();
}

the keen eye’d among you will notice a cheeky reference to one of my NuGet packages

There is currently only one method in the ConfigureHttpPipelineExtentions class, and that is for adding customised MVC routes:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using FullStackTemplate.Persistence;
namespace FullStackTemplate.UI
{
/// <summary>
/// This class is based on some of the suggestions bty K. Scott Allen in
/// his NDC 2017 talk https://www.youtube.com/watch?v=6Fi5dRVxOvc
/// </summary>
public static class ConfigureHttpPipelineExtentions
{
public static void UseCustomisedMvc(this IApplicationBuilder applicationBuilder)
{
applicationBuilder.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}

I agree that this is the standard MVC route, but the idea is that a consuming user could edit the contents of this method to suit their application’s requirements.

Façades

I’d decided on using Façades for controllers because it maintains the single responsibility principle, and moves all non-controller code out of the controllers.

I’ve seen quite a few MVC code bases where the Controllers did a lot of non-Controller stuff. By that I mean something like this

[Route("/[controller]")
public class EmployeesController : Controller
{
public IActionResult UpdateEmployee(EmployeeViewModel employeeData)
{
// get record from database
var dbEmployee = _employeeService.GetOrCreate(employeeData.id);
// do a bunch of validation
if (string.IsNullOrWhiteSpace(employeeData.GivenName))
{
throw new ArgumentException($"nameOf({employeeData.GivenName}) is required");
}
else if (string.IsNullOrWhiteSpace(employeeData.FamilyName))
{
throw new ArgumentException($"nameOf({employeeData.FamilyName}) is required");
}
// etc...
else
{
dbEmployee.GivenName = employeeData.GivenName;
dbEmployee.FamilyName = employeeData.FamilyName;
dbEmployee.SocialSecurityNumber = employeeData.SocialSecurityNumber;
// a bunch of other properties later
// update the entity in the database
_employeeService.AddOrUpdate(dbEmployee);
_employeeService.SaveData();
}
// re-direct the user to the relevant view
return View();
}
}

and yes, that’s based on a real controller method I once found.

What’s not so great about the above controller method is that of the 40 lines of code in the method, there is only one line which needs to be there.

can you guess which one it is?

What a controller should do (in my opinion), is it should take in the data from the client side, do validation on it, and return a response. Everything else should be the responsibility of some other service.

Currently, the above version of the controller method needs access to:

  • The Employee ViewModel
  • The Employee DB Entity Model
  • The Employee service

And that is two things too many.

So let’s reduce the surface area of the controller. What I’m about to show you is controversial, and I’ll talk you though why it’s controversial after I’ve shown you it.

The first thing should do is make the controller simpler:

[Route("/[controller]")
public class EmployeesController : Controller
{
public IActionResult UpdateEmployee(EmployeeViewModel employeeData)
{
// do a bunch of validation
if (!employeeData.Validate())
{
// we've want to do something more relevant here. This is
// an example after all
return StatusCode(500);
}
var status = _employeeFacade.UpdateEmployee(employeeData);
// re-direct the user to the relevant view
return View(status);
}
}

Anyone looking at this controller method can see, at a glance, what it does. It follows both the single responsibility principle (by taking the request, generating a response, and having something else deal with all the middle bits), and the Newspaper metaphor (as you can read it easily, or choose to drill down to get the details).

The validator could be as simple (and badly written) as this:

public static class EmployeeViewModelValidator
{
public static bool Validate(this EmployeeviewModel employeeviewModel)
{
if (string.IsNullOrWhiteSpace(employeeData.GivenName))
{
return false;
}
if (string.IsNullOrWhiteSpace(employeeData.FamilyName))
{
return false;
}
// etc.
return true;
}
}

It wouldn’t really matter, because the controller doesn’t need to know.

having a separate validation method is called a Guard Clause or Method. For more on Guard Clauses, I’d recommend this episode of Weekly Dev Tips by Steve Smith (yes, THAT Steve Smith)

And the Façade could also follow the same principles by looking like this:

public class EmployeeFacade
{
private readonly IEmployeeService _employeeService;
public EmployeeFacade(IEmployeeFacade employeeFacade)
{
_employeeFacade = employeeFacade;
}
public UpdateStatus UpdateEmployee(EmployeeviewModel employeeData)
{
// get record from database
var dbEmployee = _employeeService.GetOrCreate(employeeData.id);
// update the database model
dbEmployee.UpdateDbModel(employeeData);
// update the entity in the database
_employeeService.AddOrUpdate(dbEmployee);
return _employeeService.SaveData();
}
}

With the mapper looking like this:

public static class EmployeeMapper
{
public static void UpdateDbModel (this EmployeeDbEntity dbEmployee, EmployeeViewModel viewModel)
{
dbEmployee.GivenName = employeeData.GivenName;
dbEmployee.FamilyName = employeeData.FamilyName;
dbEmployee.SocialSecurityNumber = employeeData.SocialSecurityNumber;
// etc.
}
}
Why The Controversy?

This is a controversial model because you still have to do the work, down the line; and you run the risk of separating things out and making them more complex. It also means that you have to traverse through several files and layers of abstraction to get a full understanding of how the whole façade method works.

I feel like it’s worth the effort to read through the façade, though. As it helps to hide away as much detail as possible. But that’s just my personal opinion.

Converting A Solution Into A Template

Now that I’ve talked through FullStackTemplate, it’s time for the main attraction.

drums, please

So you want to take as pre-existing template and make it into a template, increasing the speed at which you can make your amazing applications? Look no further.

The first thing we need to do is to prepare the solution. This is why I specifically built FullStackTemplate, but you can use any pre-existing template you wish. This might include cleaning up or removing some code, but it’s easy enough to do and out of the scope of this article.

Once your solution is in the right shape and is ready to be converted into a template, we need to create a Unix style hidden directory.


If you’re a Windows user, this does not mean right-clicking and setting the directory to hidden in it’s properties. In Unix-like operating systems, you can hide a directory by prefixing it’s name with a dot (or ‘.’ character). For example: “.userSecrets” is a Unix-style hidden directory.

for more on Unix-style hidden directories, take a look at this wiki article


The hidden directory needs to be called .template.config and needs to be placed in the root of the solution directory. For example:

template.config directory
Here is the root of my FullStackTemplate solution

In the above screenshot, the red arrow is pointing at the .template.configdirectory.

you’ll may need to show hidden directories in your file explorer

This is an important directory and will contain the config for your template

talk about bleeding obvious

and within this directory, we need to add a file called template.json.

Here is the template.json file for FullStackTemplate:

{
"author": "Jamie Taylor",
"classifications": ["Web"],
"name": "Full Stack Template",
"identity": "FullStack.Template",
"shortName": "fullstack",
"tags": {
"language": "C#"
},
"sourceName": "FullStackTemplate",
"preferNameDirectory": "true"
}

Let’s talk a walk through this file

it wont take long, honest

template.json
{
"author": "Jamie Taylor",
"classifications": ["Web"],
"name": "Full Stack Template",
"identity": "FullStack.Template",
"shortName": "fullstack",
"tags": {
"language": "C#"
},
"sourceName": "FullStackTemplate",
"preferNameDirectory": "true"
}

I’ve highlighted the lines of code which are used by the output of dotnet new --list.

  • classifications is an array and is used in the tags list for the template
  • name (surprisingly) is the name of the template
  • identity is used as a namespace-like id for the template
  • shortname is used as a handy short name for the template

gotta save those key strokes

  • tags is a useful array of properties for sorting and ordering our templates
  • sourcename this is the most powerful of the above properties

The sourcename property is used by the .NET Core SDK as a find and replace key to ensure that solutions created with the template all have the correct names for projects and namespaces.

Using FullStackTemplate as an example, whenever we create a new solution from this template

more on that in a moment

FullStackTemplate will be replaced, across all of the files created, with the name that we supply for the new solution.

Installing A Local Template

Assuming that we’ve created the template solution and filled in the template.json file in the .template.config directory, all we have to do is issue a command based on the following:

dotnet new --install /path/to/parent/of/.template.config

Where /path/to/parent/of/.template.config is the path to the root directory of the template solution.

As a more concrete example, here is the command I would run on my machine, in order to install FullStackTemplate:

dotnet new --install ~/Code/FullStackTemplate/

This works because I have all of my code cloned down to ~/Code

for Windows users, this is the equivalent of my Users directory, with a sub-directory called Code

When that command has completed, you’ll see the following output:

Templates Short Name Language Tags
--------------------------------------------------------------------------------------------------------
Console Application console [C#], F#, VB Common/Console
Class library classlib [C#], F#, VB Common/Library
Unit Test Project mstest [C#], F#, VB Test/MSTest
xUnit Test Project xunit [C#], F#, VB Test/xUnit
Full Stack Template fullstack [C#] Web
ASP.NET Core Empty web [C#], F# Web/Empty
ASP.NET Core Web App (Model-View-Controller) mvc [C#], F# Web/MVC
ASP.NET Core Web App razor [C#] Web/MVC/Razor Pages
ASP.NET Core with Angular angular [C#] Web/MVC/SPA
ASP.NET Core with React.js react [C#] Web/MVC/SPA
ASP.NET Core with React.js and Redux reactredux [C#] Web/MVC/SPA
ASP.NET Core Web API webapi [C#], F# Web/WebAPI
global.json file globaljson Config
Nuget Config nugetconfig Config
Web Config webconfig Config
Solution File sln Solution
Razor Page page Web/ASP.NET
MVC ViewImports viewimports Web/ASP.NET
MVC ViewStart viewstart Web/ASP.NET

Which is the same as running dotnet new --list.

Using the Template

Using the new template from the terminal is extremely simple. Once it’s installed, run the following command:

dotnet new templateName --name MyProject

Substituting the shortname property for FullStackTemplate into the above (and using a useful name), we get the following command:

dotnet new fullStack --name fullStackDemo

Which should respond with something similar to the following:

The template "Full Stack Template" was created successfully.
Uninstalling the Template

The time may come when you need to retire the template

for whatever reason

and doing that is almost as simple as installing it in the first place. Here is the vague version of the command:

dotnet new --uninstall /path/to/parent/of/.template.config

And here is the version of the command I would run to remove FullStackTemplate:

dotnet new --uninstall ~/Code/FullStackTemplate/

remember, I have my code cloned down to ~/Code

And that’s about it.

External Resources

For more information on creating templates in .NET Core, I’d check out the following resources:

I’d start here, as this is the repo for the templating engine and there are links to a number of the popular templates which you can install from the terminal.

This goes into more depth about some of the things you can do with templates (like conditional includes, parameters, and all sorts of cool stuff).

If videos are more your thing, then I would check out this video of Sayed talking Jon Galloway through the process of creating a template (almost from scratch).


Have you created any .NET Core 2.0 templates? Are they open or closed source? I’ve shown you mine, care you share yours?

ooh er

Would you be more willing to create your own templates now that you know how?

What do you think of FullStackTemplate? How would you improve it?

Pull requests are welcome, so if there’s something which could be improved then please do

Let me know in the comments and let’s keep the conversation going.

Related Posts

A .NET developer specialising in ASP.NET MVC websites and services, with a background in WinForms and Games Development.

When not programming using .NET, he is either learning about .NET Core (and usually building something cross platform with it), speaking Japanese to anyone who’ll listen, learning about languages, writing for his non-dev blog, or writing for a blog about video games (which he runs with his brother)