Please Note: This post was updated in Jan 2015 to accomodate an upgrade to TemplateBuilder. All images and sample code have been updated.

Overview

Recently I've been working on an AngularJS project, using Visual Studio. As part of my role I've been trying to ensure code consistency and quality, but many people on the team are new to Angular and so everyone seems to have their own way of laying out a controller, directive, etc. To try to improve this situation I decided to create a Visual Studio extension that we can use to create templates for all angular 'types' (e.g. Controller, Directive, etc.) and any other JavaScript files we need to create (e.g. Jasmine Specs).

After some investigation I found we could use SideWaffle but this didn't give us the freedom to define the templates. While SideWaffle is an excellent pack of templates for all kinds of languages, we want to be able to come up with a template as a team and use that going forward.

Pre-requisites

If you intend to create your own template pack you'll need to ensure you've considered the following pre-requisites:

  • Visual Studio SDK - We need to install the VS SDK for your version. I'm using Visual Studio 2013, so the SDK I used can be found here.

  • TemplateBuilder - This is a nuget package that can be added to your template project, which is used in the development of the SideWaffle. You can find Template builder here.

Steps

Project Set-up

First we have to create a Visual Studio Package project (shown below). If you can't see the "Visual Studio Package" project in the new project list, then chances are you don't have the Visual Studio SDK installed.

Create Project Image

After setting the package name and location you're taken through the Visual Studio Package Wizard. This wizard prompts you to choose your language (C#, VB or C++) and it asks you to generate a new key to sign the assembly. After this step you're prompted to enter information about your company, package name, etc. This information will be used to display the extension.

In step 3 (of 7) of the package wizard you're asked to select your package options from choices of "Menu Command", "Tool Window" and "Custom Editor". But for a simple template project we don't need to select any of these options.

The final step in the wizard is to select test project options. I opted to not include any integration or unit test projects in my solution.

Add Nuget Packages

Next, (as stated in the pre-requisites) we need to add the TemplateBuilder nuget package.

To do this open the Nuget Package Manager and search for "TemplateBuilder". Then install the package.

Nuget TemplateBuilder Package

When this package has been added you should see the following changes in your project:

  • ItemTemplates and ProjectTemplates assets are added in the VSIXManifest (shown below).
  • The build process is altered to include building of the new assets.

VSIXManifest Updates

TemplateBuilder is also supposed to create "ItemTemplates" and "ProjectTemplates" folders in the root of the project. But sometimes this doesn't happen for me. So we'll cover the required folders in the next step.

Project Folders

As previously mentioned, if the folders aren't automatically created for you then we need to create the following in the root of the project:

  • ItemTemplates - Contains the file templates (e.g. AngularJS controller).
  • Resources - As the name implies, it contains any resources needed in the project.

Update Metadata and Images

The final step in the set-up process is to apply any meta data and images/icons you want linked to the extension when it's viewed in Visual Studio.

To update the metadata, review the VSIXManifest and update as required. I usually update tags, release notes, and add a more info URL.

Update Metadata

On the above screen you can also assign an icon and preview image. The icon is used in the Visual Studio "Add File" dialog, and both are used in the Visual Studio Extensions dialog (shown later in the post).

Any images or icons you add here should NOT be stored in the Resources folder of the project as the contents of this folder are included as embedded resources. So the images I've used are in the root of the project (named icon.png and logo.png respectively).

The final piece of metadata to update is the template sub folder. This can be found in Properties > template-builder.props (xml shown below):

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- 
    You can override TemplateBuilder properties here.
   -->
  <PropertyGroup>
    <!-- This is the subfolder name where the templates will show up in Visual Studio. -->
    <ls-TemplateSubFolder>SJCNet Templates</ls-TemplateSubFolder>

    <!---
    You can set the following property to false to disable creating the template report
    -->
    <!--<ls-GenerateTemplateReport>false</ls-GenerateTemplateReport>-->
  </PropertyGroup>
</Project>

Create File Templates

The next step is to create some file templates. For this example I'm going to create AngularJS controller and Jasmine Spec templates.

Folder Structure

I recommend keeping the folder structure organised to avoid confusion as the amount of templates increases. For my example I've created the following structure:

Template Folder Structure

File Template

In the file template folder (e.g. the Web/Angular/Controller folder) we need to add three things:

  • Definitions - We add a definitions folder to contain the template definitions for C#, VB, Web, etc. In my case the template is the same (as it's a Javascript template) but this illustrates how to create different templates for C# and VB.
  • Template - This is the actual template. In my case I've added a controller.js file which is laid out in the style that's been agreed with the team.
  • Icon - This icon will be shown in the Add File dialog along side the template. The link to this icon needs to be set in the definitions.

Definitions

As previously mentioned, we need to create definitions for different languages/areas of the Add File dialog. The definition file also allows us to specify additional metadata that's specific to this template (shown below):

<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Item">
  <TemplateData>
    <DefaultName>controller.js</DefaultName>
    <Name>AngularJs Controller using 'Controller as'</Name>
    <Description>AngularJs controller using 'Controller as' laid out according to agreed standards.</Description>
    <ProjectType>CSharp</ProjectType>
    <Icon>icon.png</Icon>
    <NumberOfParentCategoriesToRollUp>1</NumberOfParentCategoriesToRollUp>
  </TemplateData>
  <TemplateContent>
    <References />
    <ProjectItem ReplaceParameters="true">controller.js</ProjectItem>
  </TemplateContent>
</VSTemplate>

Above you can see I've specified the icon file, a name, description and project type (C# as this is the C# definition file).

Once you've created the templates and related files, it's time to debug!

Debugging

You can debug Visual Studio package projects in the usual way (hitting F5). When you do this the IDE opens up a debug version of Visual Studio with your extension installed and ready for use.

So, to test my extension I have to create (or open) a web project in the debug version of Visual Studio. Then right-click in the Solution Explorer and choose Add > New Item. Below you can see the templates I've created as part of my extension.

Add File Dialog

Additionally, if we go to the Tools menu and select Extensions and Updates I see the following:

Extensions and Updates Dialog

Wrap Up

This post has covered how to create a Visual Studio extension that you can use to manage custom file templates. I've also covered what you need and how you can add metadata and images to make your extension look professional.

You can download the source project from here.

Please Note: If you have problems getting the sample project to debug, open the project properties and on the Debug tab set the Start external program value to the path of your Visual Studio devenv.exe. For example, my path is:

C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\devenv.exe

Any comments please add them below... Just so that I know someone other than me is reading this stuff :)