Introduction

A number of predefined project and item templates are installed with Visual Studio. These templates, such as the ASP.NET Web Application and Class Library templates, are available to choose from when you create a new project. Item templates, such as code files, XML files, HTML pages, and Style Sheets, appear in the Add New Item window.

These templates provide a starting point for users to begin creating projects, or to expand existing projects. Project templates provide the files that are required for a particular project type, include standard assembly references, and set default project properties and compiler options. Item templates can range in complexity from a single empty file that has a certain file extension, to multiple source code files with stub code, designer information files, and embedded resources.

Multi-project templates act as containers for two or more projects. When you create a project that’s based on a multi-project template, every project in the template is added to the solution. A multi-project template has two or more project templates, and a root template of type ProjectGroup. Multi-project templates behave differently than single project templates.

Required Tools

Required steps

Steps involved to create a multi-project template for visual studio can be enlisted as below:

  1. Create a blank solution
  2. Addition of common project (.NET Framework class library)
  3. Addition of extension class for common project
  4. Addition of service project (.NET Framework ASP.NET Web API)
  5. Removing unused libraries
  6. Removing unused files and codes.
  7. Customization of project structure
  8. Referencing common project to service project
  9. Export template wizard
  10. Copying exported files
  11. Create root.vstemplate
  12. Managing project references dynamically
  13. Compression to create template
  14. Copying to ProjectTemplate
  15. Creating new project based on template
  16. Re-installation of packages
  17. Importing references

Step 1: Create a blank solution

First step to create a template will be to create a blank solution. Blank solution can be created by selecting File->New->Project and searching ‘blank solution’.

1_Blank Solution

Step 2: Addition of Common project (.NET Framework class library)

In the next step, we will add a new project to the solution. Right click at the solution and then select add -> New project. Select ‘Class Library (.NET Framework)’ and provide the name of the project. In this case, we have provided ‘Susen.SourceProject.Common’ name to the project. We can provide any name to the project.

2_CommonProject
Addition of common project

Following figure shows the solution explorer once a project is created.

3_ProjectStructure
Project structure of Common project

Step 3: Addition of extension class for common project

We will add two extension classes in this project, solely for testing purposes. AsyncHelper and JsonExtension will be added as an extension class in this project. We’ll also need to add Newtonsoft.Json through nuget package since JsonExtension will be using it.

4_ProjectStructure
Project structure of Common project

Above figure displays the project structure of Common project.

 

Step 4: Addition of service project (.NET Framework ASP.NET Web API)

Afterwards, we will move forward to create another project. This time, we will select ‘ASP.NET Web Application (.NET Framework)’ and provide project name. In this case, we have provided project name as ‘Susen.SourceProject.Services’. Once we click ‘OK’, another window will be displayed with ASP.NET templates. We will select Web API and finalize the project creation.

5_ServiceProject
Add new project menu

Above figure shows the process to create a new ASP.NET Web Application

 

6_ServiceProject
ASP.NET Templates

Above figure displays selected ASP.NET Web template.

 

7_ProjectStrucuture
Default project structure

And this is how a default ASP.NET Web API project will look. We will tweak the project structure in upcoming steps.

 

Step 5: Removing unused libraries

In order to keep template clean, we will remove unused bloatware libraries which are installed with ASP.NET Web API template by default. Following are the libraries which we have removed from Service project.

If we need to add these removed projects, we can always add them back through nuget package.

Step 6: Removing unused files and codes

With the same objective as of previous step, i.e. to keep template clean, we will also remove unused files and codes. In the service project, we will remove codes and files as below:

8_ProjectStructure
Project structure after removing unused files

This is how project structure will look after cleaning up unused files and codes.

 

Step 7: Customization of project structure

Project structure can be customized according to the requirement and demands of the project. In this article, we will be adding business access, data access, entities, handlers and services in the project structure. We can always modify the structure of a project according to the requirements. In the project, we will be adding following directories and classes to customize the project structure.

Business Access

  1. Interfaces
  2. Mocks
  3. Services

DataAccess

  1. Abstract

           1.1. Database.cs

           1.2. Repository.cs

  1. Databases

           2.1. SqlDatabase.cs

           2.2. UserContext.cs

  1. Interfaces

           3.1. IDatabase.cs

           3.2. IReposiotory.cs

           3.3. IUserContext.cs

DataAccess.Data

  1. DataConstants.cs
  2. DataExtensions.cs

DbUp

  1. Scripts

Entities

  1. Args

           1.1. Abstract

  1. Results

Handlers

Services

  1. Abstract
  2. Interfaces
  3. Proxies
  4. Requests
9_AdditionInProjectStructure
Project structure after customization

Our service project structure will look as displayed on above figure after we have modified its structure.

Step 8: Referencing common project to service project

In this step, we will implement the final processes required before exporting a template.

In order to user common project within service project, we will need to add its reference. Reference can be added by right-clicking project, Add-> References… and selecting the common project.

10_AddReference
Addition of Common project’s reference

For testing purposes, we will add following code in Index action of HomeController.

using System.Web.Mvc;
using Susen.ResultProject.Common.Extensions;

namespace Susen.ResultProject.Services.Controllers
{
   public class HomeController : Controller
   {
       public ActionResult Index()
       {
           string testData = "TestColumn";
           string result = testData.ToCamelCaseColumnName();
           ViewBag.Title = result;

           return View();
       }
   }
}

Above code will simply use ToCamelCaseColumnName() method of JsonExtensions which is imported from Common project. We can see that the directory of JsonExtensions is imported from ‘using Susen.ResultProject.Common.Extensions’.

For confirmation, let’s debug the project before exporting the template

11_ToCamelCaseColumnName
Debugging Project

 

As we can see from the above figure, referenced method ToCamelCaseColumnName() is working perfectly fine.

One final step which is not mandatory is to remove the common project’s import directory. I.e. to remove ‘using Susen.ResultProject.Common.Extensions’. In case of large project, we’ll need to remove all those import lines. This step is not compulsory but is a better approach to remove errors which will be generated when creating a project through custom template.

 

12_RemoveImport
Removing import lines

After this confirmation, we are now ready to export the template with these project structures.

 

Step 9: Export template wizard

After we complete all of the above steps, the project is now ready to be exported as a template.

In order to export template, we’ll need to follow the steps as below:

The project is exported into a .zip file and placed in the specified output location, and, if selected, imported into Visual Studio. In our case, .zip file will be saved in ‘Documents\Visual Studio 2017\My Exported Templates’ directory.

 

13_ExportTemplateWizard
Choosing Export template type

 

14_2_ExportTemplate
Selecting Template options for Service project

 

14_ExportTemplate
Selecting template options for Common project

We can see that the .zip file has been exported in the figure below.

15_Exported
Exported zip files

Step 10: Copying exported files

Once all .zip file has been exported, we’ll copy/move these entire files into the directory where we will configure the multi-project template. We have copied these files at ‘\.NetTemplateExport\Template Configuration’ directory in given case. Then we will extra both of these zip files in the given directory.

16_ExtractZipFile
Extracting zip files

Above figure displays the copied zip files and its extracted folders. We can delete the zip files if we wish to.

Step 11: Create root.vstemplate

In the same directory where we have extracted the template, let’s create a new file ‘root.vstemplate’. Then we can edit the file and add following XML code.

The XML nodes of ‘root.vstemplate’ can be explained as below:

<VSTemplate Version="2.0.0" Type="ProjectGroup"
   xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
   <TemplateData>
       <Name>Susen Template</Name>
       <Description>Custom ASP.NET Web services project</Description>
       <Icon></Icon>
       <ProjectType>CSharp</ProjectType>
   </TemplateData>
   <TemplateContent>
       <ProjectCollection>
               <ProjectTemplateLink ProjectName="$safeprojectname$.Common">
                   Susen.Common\MyTemplate.vstemplate
               </ProjectTemplateLink>
               <ProjectTemplateLink ProjectName="$safeprojectname$.Services">
                   Susen.Services\MyTemplate.vstemplate
               </ProjectTemplateLink>
       </ProjectCollection>
   </TemplateContent>
</VSTemplate>
  1. TemplateData:  This node will contain sub-nodes which will be used to display while creating a new project.

           1.1. Name: We will provide the name of a template in this node. This field is mandatory.

           1.2. Description: Here we will provide the description of a template.

           1.3. Icon: We can provide icon image to be displayed for template in this node.

           1.4. ProjectType: We’ll add CSharp in this node since out project is based on C#.

  1. TemplateContent: This template contains sub node to define template structure and its contents.

            2.1. ProjectCollection: In this node, we will add sub-node ProjectTemplateLink to link with an individual template. We can add multiple sub-                          nodes in this ProjectCollection node.

           2.2.1. ProjectTemplateLink: In this node, we will provide the name of individual project and location of its template. In order to dynamically                             create a project name, we can add $safeprojectname$ in ProjectName attribute. It can be customized according to the requirement.

Step 12: Managing project references dynamically

In order to make project reference dynamic, we’ll need to edit the .csproj file of Service project. In broad case, we’ll need to edit every reference to make them dynamic with template. In .csproj file, we’ll need to find ProjectReference node and edit its attributes and sub-nodes.

In our case, we’ll need to edit the solution name dynamically by replacing static solution name with $(SolutionName) in ‘include’ attribute and ‘Name’ sub-node. Because, whenever we create a new project based on custom template, its project name should match with the solution name. If not, the project name will always be constant.

I.e. whatever we provide the name to the custom template project, it will always reference as ‘Susen.SourceProject.Common’ which will be invalid. In such case, we will need to manually remove the reference and add the common project’s reference.

 

17_PreCsProject
Before editing project reference

This is how ProjectReference will look like before we edit .csproj file.

 

2_PostCsProj
After editing project reference

And this is how ProjectReference will look after editing .csproj file. Once this step is completed, then the project reference will be dynamic based on it’s solution name.

Step 13: Compression to create template

After completing step 12, we are now ready to create a multi-project template. We’ll need to compress all individual templates along with ‘root.vstemplate’ into one .zip file.  We need to select all the individual templates and ‘root.vstemplate’ and click right-click -> Send to -> and click ‘Compressed (zipped) folder’ and provide any suitable name for .zip file.

19_Compress
Compressing to create a final template

After compression, the directory will be displayed as figure below. Here we have compressed required files into ‘Susen.CustomProject.zip’ file.

20_AfterCompress
Creation of final template

Step 14: Copying to ProjectTemplate

Once multi-project template’s .zip file has been created, we’ll need to copy or move it into the ProjectTemplate directory of visual studio. It is located in ‘Documents/Visual Studio 2017/Template/ProjectTemplates’ directory.

21_CopyToProjectTemplates
Copying template to ProjectTemplate directory

ProjectTemplates directory will look as above figure after copying the .zip file. The template is now ready to be used.

Step 15: Creating a new project based on template

Re-open the Visual Studio, and from the file menu, select New -> Project …

Select Installed -> Visual C# menu and there we can find our newly created custom template as ‘Susen Template’. Select it and provide a name to the project, then click OK.

 

1_ProjectCreation
New project with custom template

 

Project with custom multi-project template is now successfully created.  Its project structure can be seen as shown in following figure.

23_ResultProjectSructure
Project structure based on custom template

Step 16: Re-installation of packages

After project has been created, we’ll need to reinstall the packages. We will use it since references to a package might get broken within a Visual Studio project. In these cases, uninstalling and then re-installing the same version of the package will restore those references to working order. We can reinstall packages through package manager console. It can be opened through Tools menu -> Nuget Package Manager -> Package Manager Console.  Nuget command to re-install packages is

update-package -reinstall'

24_Package_Reinstall

 

Step 17: Importing references

If we go back to step 8, we have removed the import references of common project. It is also explained there that we can keep those import reference if we want since it isn’t a mandatory process. However if we had chosen the latter option, there would’ve been an error while creating a project with multi-template project. There will be ‘using Susen.SourceProject.Common.Extensions;’ instead of ‘using Susen.ResultProject.Common.Extensions;’. We would have to manually remove those import lines.

But if we had chosen the first option, we will only need to import the reference which can be easily achieved in visual studio (ALT+ ENTER or ALT+.).

25_Import
Importing missing references

Testing project

Now let’s test if the project is working. We’ll need to set Service project as a Startup project and then run the project in debug mode.

26_ResultProject_Test
Confirming if project is working

As we can see in the above figure, the project is working fine. Hence we can conclude that the multi-project template’s project is successfully created.

Conclusion

Project templates are easy to customize, and they can help us avoid repetitious setup efforts.  These tools can be used for a diverse array of purposes, but one of the primary benefits of templates is the rate of completion they lend to projects ranging in size and necessary effort. Instead of developing a new project every time we send a memo or a design pitch, you can reuse the template and simply change the desired information. All the codes and files used to create this test project can be accessed from GitHub.

References

Leave a Reply

Your email address will not be published. Required fields are marked *