Visual Studio: How to create a solution template with multiple projects

After a while of creating the same solution structure code over and over again for the some kinds of projects I decided to make a template. Making a single project template was easy: you just follow along the Visual Studio export template wizard but making a solution template with multiple projects was not as simple, hence the reason for this blog post.

I’m using a PC with Windows 8.1 Pro and Visual Studio 2013 with update 4.

Setup Solution
First set up a solution with the projects you want to make into a template. For this example I’ll go with a really simple and stripped down skeleton for a backend solution following the domain driven design. You can fork it here. It’s just a really simple skeleton solution with multiple projects, feel free to go wild and crazy adding stuff and altering it as you like for your template.

This is what my demo project structure looks like
1. solutionsetup

In order to make this into a Visual Studio template we need a .vstemplate file in the root as well as in each project we want to include in the final solution template. The easiest way is to use the template export wizard to export the projects one by one and then add the root template.

Export each project
Go to File Export Template…
2. export project

Leave the Project template radio button checked and choose one of the projects in the drop down list
3. project template

Fill out the template options as you want them and click finish.
4. export DataAccess project

The file explorer should pop up with My Exported Templates where your newly exported project is neatly packed into a .zip file. Go ahead and look inside to see to the basic structure and notice that a MyTemplate.vstemplate file is present
5. exported dataaccess zip

Extract the zip file a folder. I’m going to change the name of the Visual Studio Project/Item Template File to DataAccess but you can leave it as is if you want.
6. exported dataaccess folder

I will also change a little thing inside the template metadata by opening the now named DataAccess file with Visual Studio. Here you can see the  .vstemplate ending which is what I’ll refer to for the rest of the post.
8. dataaccess vstemplate file

I’ll change the <Name> tag to DDD Backend Data Access  which will make my DataAccess.vstemplate metadata look like this:

<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
  <TemplateData>
    <Name>DDD Backend Data Access</Name>
    <Description>Domain Driven Design: Data Access layer</Description>
    <ProjectType>CSharp</ProjectType>
    <ProjectSubType>
    </ProjectSubType>
    <SortOrder>1000</SortOrder>
    <CreateNewFolder>true</CreateNewFolder>
    <DefaultName>DDD_Backend.DataAccess</DefaultName>
    <ProvideDefaultName>true</ProvideDefaultName>
    <LocationField>Enabled</LocationField>
    <EnableLocationBrowseButton>true</EnableLocationBrowseButton>
    <Icon>__TemplateIcon.ico</Icon>
  </TemplateData>
  <TemplateContent>
    <Project TargetFileName="DDD_Backend.DataAccess.csproj" File="DDD_Backend.DataAccess.csproj" ReplaceParameters="true">
      <Folder Name="Properties" TargetFolderName="Properties">
        <ProjectItem ReplaceParameters="true" TargetFileName="AssemblyInfo.cs">AssemblyInfo.cs</ProjectItem>
      </Folder>
    </Project>
  </TemplateContent>
</VSTemplate>

Now repeat this process for each project in the solution. My folder looks like this:
7. all projects are exported

The Solution Template
We are now ready for creating the Root.vstemplate file which will be what binds our project templates together with the solution template. Open up an empty Visual Studio and go File New File…
9. new file

Choose XML File and open
10. open XML File

I want all my projects to match my naming convention: “ProjectName.LayerName” and this is done by using a  template parameter such as $projectname$. This parameter will be replaced by your input file name in the New Project wizard in Visual Studio.

Paste the following into the xml document:

<VSTemplate Version="3.0.0" Type="ProjectGroup" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
  <TemplateData>
    <Name>DDD Backend Solution Template</Name>
    <Description>Domain Driven Design: Backend Solution Template</Description>
    <ProjectType>CSharp</ProjectType>
    <ProjectSubType>
    </ProjectSubType>
    <SortOrder>1000</SortOrder>
    <CreateNewFolder>true</CreateNewFolder>
    <DefaultName>DDD_Backend</DefaultName>
    <ProvideDefaultName>true</ProvideDefaultName>
    <LocationField>Enabled</LocationField>
    <EnableLocationBrowseButton>true</EnableLocationBrowseButton>
    <Icon>DDD_Solution_icon.png</Icon>
  </TemplateData>
  <TemplateContent>
	<ProjectCollection>
            <ProjectTemplateLink ProjectName="$projectname$.DataAccess">
                DDD_Backend.DataAccess\DataAccess.vstemplate
            </ProjectTemplateLink>
            <ProjectTemplateLink ProjectName="$projectname$.Domain">
                DDD_Backend.Domain\Domain.vstemplate
            </ProjectTemplateLink>
	    <ProjectTemplateLink ProjectName="$projectname$.Repository">
                DDD_Backend.Repository\Repository.vstemplate
            </ProjectTemplateLink>
	    <ProjectTemplateLink ProjectName="$projectname$.Services">
                DDD_Backend.Services\Services.vstemplate
            </ProjectTemplateLink>
        </ProjectCollection>
  </TemplateContent>
</VSTemplate>

Save the file in the root of the folder where you have your project template folders  and make sure it ends with .vstemplate which will convert it to a template file. I’ll call mine Root.vstemplate
11. save as root
12. root

Alright! We are nearly done. I just want to add a template icon for the solution with the name I specified in the root.vstemplate file <Icon>DDD_Solution_icon.png</Icon>

13. solution icon

Now zip the files in this folder by marking them all  Right-click Send to Compressed (zipped) folder
14. compress folder

Give it a name and add it to your ~\Visual Studio version>\Templates\ProjectTemplates folder
15. add to project templates

Done! You can now go to New Project in Visual Studio and find the solution template like you would normally do and give it a name.
16. create new DDD project

And there you have it =)
17. new solution project

This Post Has 38 Comments

  1. A tutorial very well done. Very useful .
    Thank You!

  2. Great article

  3. I had been wondering if there was more than just exporting a single project template. Thanks for the detailed tutorial!

  4. Hey, How would this be done and then packaged into a VSIX project? When i create a new Project template and configure the vstemplate file to get the other selected vstemplates; it seems to work. But, once created, it only makes a folder which is empty.

  5. When I follow the directions, Each project is show, not the solution. It works somewhat, but I want it to create the solution with each project as yours does. Did you miss a step in the directions? I am using VS 2012.
    Please reply.
    Thanks,
    Mike

  6. What about dll references? If there’s a dependency between template projects, will it still work?

  7. Hello, is it possible to add “solution items” in the template?

  8. Thank you very much for your great article. If I create a new project with the new template the solution file is not located in the right directory like in your example repository.

    Do you know a workaround for this?

  9. Great article, thank you for posting!

    However I’m having problems with references not being brought over. I mean, they are listed, the ‘packages’ folder content is there, but the Solution doesn’t know it.

    Do I have to include this in any way, inside my Root.vstemplate or any of the included project .vstemplate files?

    Thank you so much in advance!

    1. Hi,
      I have the same problem, references are there, but broken (with the yellow exclamation mark).
      Does this work when you have nuget packages installed on the projects?

      1. For all of the references to other assmeblies (both in code files and in the csproj files) you need to replace the hard coded assembly values with $ext_safeprojectname$.

        The ext_ gets the project name from the parent in this case, the solution level, so and example would be

        using MyProject.MyOtherAssembly.MyOtherResource;

        namespace MyProject.MyAssembly.MyResorce {}

        would be:
        using $ext_safeprojectname$.MyOtherAssembly.MyOtherResource;

        namespace $safeprojectname$.MyResorce {}

  10. Arnie and Renato: The broken references are because when new solution is created, it creates an extra folder level for the projects inside the solution folder. This breaks the original reference to the packages folder which is supossed to be one level above project files and now is 2 levels above.
    I still can’t find a fix to avoid this behavior and I was expecting to find it here, but to no avail :(
    Elizabeth??

  11. BTW: My only workaround so far (though kind of nasty to my taste) is to edit the project files from each project template to change the paths of the nuget dependencies from “..\packages” to “..\..\packages”. That should point the packages folder in the solution root and make the projects work without issues.

    1. I know! I’t sdisgusting, right?! I haven’t seen as bad a feature as this in Visual Studio ever!

  12. Thank you! I’ve been trying to do this for years and haven’t been able to. This method worked very well for me.

  13. Great article, Elizabeth. I have a couple of queries related to it:

    1) Why do we need to create multiple projects under one solution? Does it help development of large, complex application?
    2) Wouldn’t it be simpler enough to create Folders in one project, in one solution?

    I am trying to understand what are the pros and cons of developing large, complex application by:
    I) having single project in one solution
    II) having multiple projects in one solution

    Thanks!

    ~ Harshit

  14. Very very good article

  15. Elizabeth, thank you!
    It was really simple and helpful!

  16. Great Article !!! Thanks

  17. Very good. Thanks.

  18. Thanks for article. If my projects are to reference other projects in solution, how do I fix up the references in the individual project files to reflect the given name of each of the projects. I have created a multi-project solution template with the following projects
    MyTemplate.Models
    MyTemplate.Repositories

    My MyTemplate.Repositories project has a reference to MyTemplate.Models. When I create a new project from this template and give the project name as MyProject, I get a solution with the following projects
    MyProject.Models
    MyProject.Repositories

    The problem Im having is that the reference from MyProjectRepositories to MyProject.Models is broken because it is defined as

    which doesnt exist. Using $safeprojectname$ instead of MyProject does not work as it replaces as this

    Any help appreciated

    1. I dug around in MSDN for a bit and found this helpful looking document

      https://msdn.microsoft.com/en-us/library/8wba5h42(v=vs.100).aspx

      It suggests that you can simply use $safeprojectname$ inside of your template files.

      Example:

      using $safeprojectname$.Infrastructure;
      using DDD_Backend.Core.Domain.Identity;
      using DDD_Backend.Core.Extensions;
      using DDD_Backend.Core.Infrastructure;
      using DDD_Backend.Core.Repository.Identity;
      using DDD_Backend.Data.Identity;
      using DDD_Backend.Data.Infrastructure;
      using DDD_Backend.Data.Repository.Identity;

      Would be typed as

      using $safeprojectname$.Infrastructure;
      using DDD_Backend.Core.Domain.Identity;
      using DDD_Backend.Core.Extensions;
      using DDD_Backend.Core.Infrastructure;
      using DDD_Backend.Core.Repository.Identity;
      using DDD_Backend.Data.Identity;
      using DDD_Backend.Data.Infrastructure;
      using DDD_Backend.Data.Repository.Identity;

      would be typed as

      using $safeprojectname$.Infrastructure;
      using $safeprojectname$.Core.Domain.Identity;
      using $safeprojectname$.Core.Extensions;
      using $safeprojectname$.Core.Infrastructure;
      using $safeprojectname$.Core.Repository.Identity;
      using $safeprojectname$.Data.Identity;
      using $safeprojectname$.Data.Infrastructure;
      using $safeprojectname$.Data.Repository.Identity;

      Visual Studio does the rest of the databinding during project creation.

    2. Add copyParameters=”true” in Root.vstemplate like below

      Use $ext_projectname$ inthe code to resolve project name

      using Provider.$ext_projectname$

  19. Muchas gracias :)
    Very good post.

  20. Hi,

    Thanks for the Great Article. Can i change the projects at runtime ? im creating a template, in which i need to ask user that, what are the projects needs to be included in Solution.

    Thanks,
    Muthukumar A

  21. For those having trouble dealing with references to other projects, I dug around in MSDN for a bit and found this helpful document: https://msdn.microsoft.com/en-us/library/8wba5h42(v=vs.100).aspx

    It suggests that you have to manually use $safeprojectname$ inside of your template files where you refer to the root namespace, and Visual Studio will take care of the data binding.

    Example:

    using $safeprojectname$.Infrastructure;
    using DDD_Backend.Core.Domain.Identity;
    using DDD_Backend.Core.Extensions;
    using DDD_Backend.Core.Infrastructure;
    using DDD_Backend.Core.Repository.Identity;
    using DDD_Backend.Data.Identity;
    using DDD_Backend.Data.Infrastructure;
    using DDD_Backend.Data.Repository.Identity;

    Would be typed as

    using $safeprojectname$.Infrastructure;
    using $safeprojectname$.Core.Domain.Identity;
    using $safeprojectname$.Core.Extensions;
    using $safeprojectname$.Core.Infrastructure;
    using $safeprojectname$.Core.Repository.Identity;
    using $safeprojectname$.Data.Identity;
    using $safeprojectname$.Data.Infrastructure;
    using $safeprojectname$.Data.Repository.Identity;

  22. Great article!

    I used your article to create a template and it worked fine, right now I want to do the same for ASP.NET Core 1.1.0 but I am unable to do it, probably due the new project type (DNX), could you be so gentle to do a new tutorial for ASP.NET Core?

    The solution I want to create the template from is this: https://github.com/adenial/TemplateCoreMaterial

    Regards

  23. Thanks,
    this gave me a great idea to create my own solution via text writing and add projects using a quick forms app for BizTalk projects.
    Cheers

  24. I rarely leave comments but it is a great post. Thanks for author.

  25. Hi,
    Nice article.
    I have the question, how to create solution/project template with .net core library that uses .net core 1.1 frameworks.
    Can u please share some sample for it?

  26. Nice article. Thanks for writing it.
    I have to make Solution Template, so when I create solution template it includes with multiple projects by using VSIX project, so what changes i need to do to make it work? Please share some sample for it.

  27. Thank you! I’ve been trying to do this for years and haven’t been able to. This method worked very well for me.

Leave a Reply

Close Menu