Volume 30 Number 6
ASP.NET - Create Your Own Visual Studio Templates with SideWaffle
By Sayed Hashimi | June 2015
Thanks to the release of the new Community Edition of Visual Studio, developers who have used the Express Editions in the past can now use the extensions they’ve heard so much about. In case you’re wondering, extensions are plug-ins that can extend the functionality of Visual Studio. There are all sorts of extensions available.
We’re always looking for ways to code more efficiently and, about a year ago, we came across an extension called SideWaffle (sidewaffle.com). SideWaffle adds new project and item templates made by other developers to Visual Studio, and it lets you create your own templates and code snippets. In this article, we’ll take a look at SideWaffle and show you how to create your own templates and snippets.
Why Use SideWaffle?
Creating a Template Pack
Before creating a template, you need to set up your development environment. The first item you need, of course, is Visual Studio. For this article, we used the Community Edition of Visual Studio 2013 (bit.ly/1GUTLo3). Next, you need the Visual Studio 2013 SDK (bit.ly/1NZVkD9). Finally, download and install the SideWaffle extension from sidewaffle.com.
With all the tools installed and ready to go, start by opening Visual Studio and creating a new project. There are two types of projects you can use to create a template pack. The first is a VSPackage project, which gives you the ability to add features like context menus or menu items in Visual Studio. The second is a VSIX project, which is just a container to hold project files and resources and doesn’t provide additional functionality. You can find both of these in the New Project dialog under the Extensibility node. Today, we want just a basic template, so a VSIX project will work. You can leave the default project name.
Once the project is created, its manifest file will open automatically. The Author field is required, so add your name (or company name) here. The Description is what will be shown in the Visual Studio extension dialog box, so be sure to add some useful text. Then save the file and close it. The next step is to add the TemplateBuilder NuGet package to the project, which you can do by using either the Manage NuGet Packages dialog or the Package Manager Console.
Let’s stop for a second now and take a look behind the scenes. When you install TemplateBuilder into a project, here’s what happens:
- A reference to TemplateBuilder.dll is added. This assembly contains custom wizards that can be used during the template-creation process, as well as other helpers.
- The project file is modified to import an additional MSBuild targets file, allowing the build process to support adding templates to the generated VSIX. Because this is implemented with MSBuild, you can build your extension on continuous integration servers and from the command line.
- A props file is added to Properties\template-builder.props. You can specify the default leaf name of the node that should contain your templates. You can also use this file to control specific aspects of TemplateBuilder.
- The VSIX manifest (typically named source.extension.vsixmanifest) is modified to include Asset tags for the generated templates.
With TemplateBuilder installed, you can start creating templates. When you build the VSIX project, TemplateBuilder automatically kicks in and starts processing the templates.
Adding TemplateBuilder to the project completes all of the preliminary requirements. Now we can add the project template to the currently open solution.
Creating the First Project Template
We’re going to use an existing project, which happens to be a generic Contoso ASP.NET Web Forms/MVC project. This project uses Bootstrap 3, jQuery and Modernizr, which will help speed up development any time we create a new project based on this template. As a rule, it’s a good idea to first run any project after adding it to the solution. This is just a precaution to make sure the project works as expected before creating the template. So run this project (Ctrl+F5) and make sure it’s working.
To create a project template, you need to do the following:
- Add the project to the solution and disable it from building.
- Add a Template Reference to the VSIX project.
- Add metadata files to the source project for template information.
To keep the template project from being built any more by Visual Studio in this solution (you can still build and run this project in other solutions), click on the dropdown menu for the build configuration and select Configuration Manager from the list. This opens the Configuration Manager dialog. To keep the project from being built, uncheck it in the Build column. Once you’ve done that for the Debug configuration, select the Active solution configuration dropdown and repeat the process for the Release configuration.
There may come a time when you want to create a template containing multiple projects. If you end up working on a complex project like that and get to this step, keep in mind the only thing that should be checked for both the Debug and Release configurations is either the VSIX project or the VSPackage project, depending on which one you chose earlier. Figure 1 shows the Configuration Manager Window after stopping the project from being built.
Figure 1 Disabling the Debug Configuration from Being Built
Next, you want to connect the VSIX project to the main project, which you’ll do by adding a Template Reference. Right-click on the VSIX project and select Add | Add Template Reference (SideWaffle project) from the options.
A Project Selector dialog will appear. From the list, select the project you want to use as your template, and click OK. This will make some changes to your VSIX project and will prompt you to reload the project. You can select the Reload All option and then wait for SideWaffle to finish.
Now, let’s add the template metadata files to the Web project. Right-click on your main project and select Add | New Item from the options listed. In the Add New Item dialog that appears, go to the Extensibility section and select SideWaffle Project Template Files. You can use the default name given by Visual Studio. Once you’ve selected the Project Template Files item template, click the Add button.
The Project Template files item adds two new files to the main project. First, it adds _preprocess.xml, which tells Visual Studio where to place your template when you open the New Project dialog. Here’s the default content for this file:
<?xml version="1.0" encoding="utf-8" ?> <Preprocess> <TemplateInfo Path="CSharp\Web\SideWaffle"/> <Replacements Include="*.*" Exclude="*.vstemplate; *.jpg;*.png;*.ico;_preprocess.xml;_project.vstemplate.xml"> <add key="ContosoWebFormsMvc" value="$safeprojectname$"/> </Replacements> </Preprocess>
In this file, you’ll find the following information:
- The path for the node where the template will appear in the New Project dialog.
- Information about source replacements.
The Path attribute on the TemplateInfo element specifies the location where the template will appear in the New Project Dialog.
Within the Replacements element, you can declare any replacements that should be applied during the template build process. You get a default replacement for the project name, which will be replaced with $safeprojectname$ in the generated template. This will typically update namespace declarations. By using $safeprojectname$ when the template is used in Visual Studio, the namespace declarations will be updated with the name specified by the user. You’re not limited to one replacement; you can add as many as needed. Sometimes you may need to modify sources to make selections unique so that replacements don’t conflict.
Now, let’s move on to the other file that was added to the project, _project.vstemplate.xml, which contains metadata about the template. Figure 2 shows the default content for the file, where ContosoWebFormsMvc is the name of the project.
Figure 2 A Generic _project.vstemplate.xml File
<VSTemplate Version="3.0.0" xmlns="https://schemas.microsoft.com/developer/vstemplate/2005" Type="Project"> <TemplateData> <Name>Your name here</Name> <Description>Project description here</Description> <DefaultName>ContosoWebFormsMvc</DefaultName> <ProjectType>CSharp</ProjectType> <ProjectSubType></ProjectSubType> <SortOrder>1000</SortOrder> <CreateNewFolder>true</CreateNewFolder> <ProvideDefaultName>true</ProvideDefaultName> <LocationField>Enabled</LocationField> <EnableLocationBrowseButton>true</EnableLocationBrowseButton> <Icon>sw-file-icon.png</Icon> <!-- Indicates how many parent folders this item template should appear in --> <NumberOfParentCategoriesToRollUp>1</NumberOfParentCategoriesToRollUp> </TemplateData> <TemplateContent> <Project TargetFileName="ContosoWebFormsMvc.csproj" File="ContosoWebFormsMvc.csproj" ReplaceParameters="true"> </Project> </TemplateContent> </VSTemplate>
This is a standard .vstemplate file; you can find the reference for this file at bit.ly/18T090m. During the template build process, files from the project will be merged into this to create the final .vstemplate file that’s used for the template. There are a few items to note here. You should update the following elements under TemplateData:
- Name: This is the name of your template as shown in the New Project Dialog.
- Description: This is the description of your project that’s shown on the right hand side of the New Project Dialog when the template is selected.
- DefaultName: This is the default name of the new project being created. A number will be automatically appended to this based on directory content.
- SortOrder: This determines the position of the templates with respect to other templates. This must be a multiple of 10; the lower the number, the higher the item is sorted in Visual Studio.
- NumberOfParentCategoriesToRollup: This determines how many parent nodes in which the template will be shown.
You should also double-check the values for the TargetFileName and File attributes on the Project tag. These should match the name of the project on disk. When TemplateBuilder processes this file, the final .vstemplate file will merge source files listed in the project. If you need special handling for any particular files, you can list those under the Project element. See the .vstemplate reference linked previously.
Now that you’ve customized both _preprocess.xml and the .vstemplate.xml file, it’s time to test the template. Make sure the VSIX project is configured as the startup project in Visual Studio and then press Ctrl+F5. This launches the Experimental Instance of Visual Studio, and your project template will be loaded automatically. Open the New Project dialog. If you go to the location that was set in your _preprocess.xml file, you should see your newly created template. Go ahead and create a new project using your new template to test it out. Make sure everything is working as expected.
If everything is working well, congratulations are in order as you just created your first project template. If you want to install this template or share it with others, go to your bin folder and find the VSIX file to install. If you or your team plans to share your project via a Git repository, there’s one additional step you need to do before uploading it.
When you create a VSIX or VSPackage project, Visual Studio updates your project file with values for the StartProgram and StartArguments tags. These values are used to ensure that F5 and Ctrl+F5 work correctly. However, these changes are configured only on a per-user basis. When you add your project to your repo, Visual Studio doesn’t include these changes. They’re saved in a .user file that’s not checked in, so when another user opens the solution and tries to run the project in an Experimental Instance, it may not work. To fix this, simply open your project’s .csproj file and add the following lines just before the end of the first property group:
<StartProgram Condition= " '$(StartProgram)'=='' "> $(DevEnvDir)\devenv.exe </StartProgram> <StartArguments Condition= " '$(StartArguments)'=='' "> /rootsuffix Exp</StartArguments>
Now run the project again just to make sure nothing got messed up. If it works as expected, you’re ready to add the project to your Git repository and share it with everyone.
You’ve just created a Visual Studio extension that contains a single project template. You can repeat this process to include additional templates in your extension. There’s no limit to the number of templates in an extension. You can share your working template with others so that they can try it. To do that you need to distribute the .vsix file that’s in the bin folder.
If you want to make your extension publicly available, you can upload it to the Visual Studio Gallery at bit.ly/115mBzm. If your extension contains more than one template (either a project or item template), the Gallery won’t accept those extensions today. Instead of uploading them directly, you can upload those extensions as a link in the Visual Studio Gallery. If you do this, you’ll need to host the .vsix file on a publicly available URL. You can use vsixgallery.com to host the .vsix file and you can use it to host nightly builds. You can easily automate publishing nightly builds to vsixgallery.com using Windows PowerShell or C#.
We’ve covered just the basics of creating project templates. There are other scenarios, such as multi-project templates, using custom wizards and more. You can look at the SideWaffle wiki on GitHub for more information. Now it’s time to move on to item templates.
Adding Item Templates
In addition to letting you create your own project templates, SideWaffle gives you the ability to create your own item templates. We’ll add to the extension project we just created.
Luckily, TemplateBuilder processes project and item templates in the same way to keep things consistent for working with both, so some of the steps for creating an item template are identical to those we already did for the project template. During the template build, item and project templates are essentially processed in the same way. If you’re getting started with a new project, make sure to add the TemplateBuilder NuGet package first.
Next, create a folder called ItemTemplates inside the VSIX project. As shown in Figure 3, this is the folder where all item templates will be stored.
Figure 3 Your Template Will Be Displayed in the Web Folder
Directly under the ItemTemplates folder you’ll create directories for your item template files. The name of the first child of ItemTemplates will be the node in which the template will appear by default. For example, in Figure 3, you can see that we created a Web folder, so templates in that folder will appear under Visual C#\Web, or Visual Basic\Web for VB or similarly for other languages. You can also use _preprocess.xml to change this, but for this sample, we’ll place all the item templates under the Web folder.
Now let’s create our first item template. For each item template, we’ll create a unique folder under Web, then add our first item template, a basic bootstrap template. To get started, create a new folder under Web named Bootstrap 3 Basic Template. This template will contain two HTML files (HTMLPage1.html and HTMLPage2.html), so place them into a folder named View. For this sample, you can use the content in Figure 4, which was taken from the Bootstrap 3 docs at bit.ly/1iKHGX3, for both files.
Figure 4 A Basic HTML5 Bootstrap Template
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Basic Bootstrap Template</title> <link href="css/bootstrap.min.css" rel="stylesheet"> <!-- HTML5 shim and Respond.js for IE8 support of --> <!-- HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE9]> <script src= "https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src= "https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> <h1>Hello, world!</h1> <script src= "https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"> </script> <script src="js/bootstrap.min.js"></script> </body> </html>
After adding the source files for creating the template, we’ll add the files that include the metadata about the item template. To do this, right-click on the Bootstrap 3 Basic Template folder and select Add New Item. As shown in Figure 5, select the SideWaffle Item Template under the Extensibility node.
Figure 5 The SideWaffle Item Template Is Located in the Extensibility Node of the Add New Item Dialog
The value in the Name text box is ignored here because the files have hardcoded filenames. When you use the SideWaffle Item Template template, you get four files in a new folder named Definitions (see Figure 6). Those four files are CSharp.vstemplat-, VB.vstemplat-, Web.csharp.vstemplat- and Web.VB.vstemplat, corresponding to the top-level languages/projects supported. CSharp.vstemplate is used for templates that will show up under the Visual C# node for C# projects. VB.vstemplate is used for templates that will show up under Visual Basic in the New Item dialog. The two Web files are to show the template for Web projects. Note that to display your template, you need to change the extension from CSharp.vstemplat- to CSharp.vstemplate. You can delete the files in which you’re not interested. As shown in Figure 6, we’ll keep all four and change the extension to .vstemplate.
Figure 6 The SideWaffle Item Template Adds a Definitions Folder and Four vstemplate Files
Now we need to edit the .vstemplate files to include the two HTML source files in the template, so we’ll add some ProjectItem elements to the CSharp.vstemplate file under the TemplateContent element. The content of the file should look like what’s shown in Figure 7.
Figure 7 A Sample _project.vstemplate.xml File with Multiple Files Added to the Item Template
<VSTemplate Version="3.0.0" xmlns="https://schemas.microsoft.com/developer/vstemplate/2005" Type="Item"> <TemplateData> <ProjectType>CSharp</ProjectType> <DefaultName>Bootstrap 3 Basic Template.txt</DefaultName> <Name>Bootstrap 3 Basic Template</Name> <Description>A basic HTML5 template using Bootstrap 3</Description> <Icon>icon.png</Icon> <NumberOfParentCategoriesToRollUp>1</NumberOfParentCategoriesToRollUp> </TemplateData> <TemplateContent> <References /> <ProjectItem TargetFileName="View/HTMLPage1.html" > View/HTMLPage1.html</ProjectItem> <ProjectItem TargetFileName="View/HTMLPage2.html" > View/HTMLPage2.html</ProjectItem> </TemplateContent> </VSTemplate>
As you can see, we added two ProjectItem entries corresponding to the two files that were created. The value of the element points to the file on disk where the template content is. The value of TargetFileName will determine the names of the files that appear when the New Item dialog is invoked.
Once you’ve added the item template and included your files, you can test the item template. Like last time, press Ctrl+F5 to open the Experimental Instance of Visual Studio, then create or open a sample project and try out your template.
Next, we’ll discuss snippets, but first a quick note about replacements. In the Project Template section, you saw how _preprocess.xml could be used to update the project content during the template build process. If you need to perform any replacements for item templates, you can use the same technique. Just as with project templates, we’ve covered only the basics of creating item templates. There’s a whole lot of ground we haven’t gotten to—using custom wizards, embedding icons as resources, nesting files and more. For information on these topics, you can refer to existing content for standard Visual Studio templates. You can also look at the wiki on the SideWaffle GitHub project page.
How to Add Snippets
We all have snippets of code we use regularly in our projects. If you’ve been wondering if there’s a way to get Visual Studio to keep track of your favorite snippets, you’re in luck. Just like before, start out by creating a VSIX project and updating the author and description fields of the source.extension.vsixmanifest.
To have Visual Studio read your snippet files, you need to create a folder structure it recognizes. Figure 8shows the structure if you were to create snippets for each programming language.
Figure 8 The Folders Shown Here Are Automatically Recognized by Visual Studio
Once you’ve created the folders you need, you can add your snippet files to the SideWaffle folder for the snippet’s respective language. As you add each file, click on the file and look at its Build Action in the properties window. Each file should have its Build Action property set to Content so Visual Studio will automatically include the file in the VSIX project when it’s built.
Next, you need to add a package definition file in the root directory of your project. The .pkgdef file will set some registry keys, allowing you to use the snippets added in the last step. Because Visual Studio doesn’t come with an Item Template for .pkgdef files, you’ll have to create a text file and rename it to use the .pkgdef extension. You can name the .pkgdef file whatever you like, but to keep things simple we named ours snippets.pkgdef. As shown in Figure 9, a different registry key needs to be updated for each language you use.
Figure 9 A Package Definition File Containing Registry Information for Each Language
The last step before you can test your new snippets is to register the .pkgdef file. Open the source.extension.vsixmanifest file, switch to the Assets tab and click on the button labeled New. The Add New Asset dialog should appear, giving you several options. As shown in Figure 10, select Microsoft.VisualStudio.VsPackage for the asset type.
Figure 10 Registering the Package Definition File with Visual Studio
Next, select File on filesystem as the source type. This will cause the dialog to expand, giving you the ability to browse to the .pkgdef file you created. Select the .pkgdef file and click OK.
Now you’re ready to test your snippets. As before, hit Ctrl+F5 to open an Experimental Instance of Visual Studio. Then open the project used earlier for testing and navigate to Tools | Code Snippets Manager. If everything loads correctly, you’re done.
We’ve now looked at the main benefits of SideWaffle so far: project and item templates and code snippets. What’s next?
The development team is currently working on a dynamic templates feature for SideWaffle that we hope to have ready for the next release. This will make it much simpler to create and maintain templates. The idea is that you can publish your templates to a Git repo or a network folder and share them with friends and colleagues. Then you can configure SideWaffle to pick up templates from the remote location. The end user will be able to control how often to check for updates. To keep up with this feature, visit the Dynamic Template page at bit.ly/18DepKM.
As you’ve seen in this article, creating your own templates is quite simple. Now that you know how to do this, you can show your friends and colleagues how much time you’re saving with SideWaffle. Remember, when sharing your template pack with the community, you’re always welcome to upload them to the Visual Studio Gallery, and vsixgallery.com is always available if you need it. If you want to share your own templates with others via SideWaffle, send us a pull request on GitHub. Now, get started creating your template pack, and let us know if you need any help.
Tyler Hughes is a recent graduate of Jacksonville State University where he studied Computer Information Systems. He has been a hobbyist developer for five years and is currently part of the SideWaffle core developer team.
Sayed Ibrahim Hashimi is a senior program manager at Microsoft on the Visual Studio Web team. He has written several books on Microsoft technologies and is the creator of SideWaffle and TemplateBuilder, as well as co-creator of OmniSharp.