Bablu Dutt
Bablu Dutt

Reputation: 359

Nested projects in multiproject visual studio templates

I need to create a vsTemplate with the following structure.

ECart - Ecart.csproject - Modules - Folder - MVC.csproject

How can we add a project within another project? In this case ECart is a web project and MVC is another project within the Modules folder of the same project.

Here is what I am trying in my template -

<ProjectTemplateLink ProjectName="ECart">
    ECart.vstemplate
</ProjectTemplateLink>
<ProjectTemplateLink ProjectName="Mvc">
    Modules\Mvc\Mvc.vstemplate
</ProjectTemplateLink>

Upvotes: 2

Views: 1089

Answers (3)

Umka
Umka

Reputation: 1

Multi-level nested multi-projects template is available! (tested on Visual Studio 2019)

Parent template parameters available in nested projects with prefix 'ext_' when you declare <ProjectTemplateLink ... CopyParameters="true">.

See Reserved template parameters - Parameter - ext_* in

Docs - Visual Studio - IDE - Develop - Solutions and projects - Customize templates - Template parameters

Result parameters values from my test:

$safeitemname$ = "Class1"
$safeprojectname$ = "SubProject1"
$ext_safeprojectname$ = "Nested"
$ext_ext_safeprojectname$ = "SolutionName"

Test description

Template file structure (in zip-archive MyTemplate.zip):

.\TopSolution.vstemplate
.\Nested\Nested.csproj
.\Nested\SupportTemplate.vstemplate
.\Nested\SubProject1\SubProject1.vstemplate
.\Nested\SubProject1\SubProject1.csproj
.\Nested\SubProject1\Class1.cs
.\Nested\SubProject2\SubProject2.vstemplate
.\Nested\SubProject2\SubProject2.csproj
.\Nested\SubProject2\Class2.cs

MyTemplate.zip:\TopSolution.vstemplate content

  ...
  <TemplateContent>
    <ProjectCollection>
      <ProjectTemplateLink ProjectName="Nested" CopyParameters="true">Nested\SupportTemplate.vstemplate</ProjectTemplateLink>
    </ProjectCollection>
  </TemplateContent>
  ...

MyTemplate.zip:\Nested\Nested.csproj content (hasn't any refs or items):

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <DebugType>full</DebugType>
    <DebugSymbols>true</DebugSymbols>
  </PropertyGroup>

</Project>

MyTemplate.zip:\Nested\SupportTemplate.vstemplate content:

  ...
  <TemplateContent>
    <ProjectCollection>
      <ProjectTemplateLink ProjectName="SubProject1" CopyParameters="true">SubProject1\SubProject1.vstemplate</ProjectTemplateLink>
      <ProjectTemplateLink ProjectName="SubProject2" CopyParameters="true">SubProject2\SubProject2.vstemplate</ProjectTemplateLink>
    </ProjectCollection>
  </TemplateContent>
  ...

MyTemplate.zip:\Nested\SubProject1\SubProject1.vstemplate content:

  ...
  <TemplateContent>
    <Project TargetFileName="SubProject1.csproj" File="SubProject1.csproj" ReplaceParameters="true">
      <ProjectItem ReplaceParameters="true" TargetFileName="Class1.cs">Class1.cs</ProjectItem>
    </Project>
  </TemplateContent>
  ...

MyTemplate.zip:\Nested\SubProject2\SubProject2.vstemplate content:

  ...
  <TemplateContent>
    <Project TargetFileName="SubProject2.csproj" File="SubProject2.csproj" ReplaceParameters="true">
      <ProjectItem ReplaceParameters="true" TargetFileName="Class2.cs">Class2.cs</ProjectItem>
    </Project>
  </TemplateContent>
  ...

Files structure created from template MyTemplate with project name 'SolutionName':

SolutionName\SolutionName.sln
SolutionName\Nested\Nested.csproj
SolutionName\Nested\SubProject1\SubProject1.csproj
SolutionName\Nested\SubProject1\Class1.cs
SolutionName\Nested\SubProject2\SubProject2.csproj
SolutionName\Nested\SubProject2\Class2.cs

MyTemplate.zip:\Nested\SubProject1\Class1.cs content (in template archive):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace $safeprojectname$
{
    public class Class1
    {
        static void Main(string[] args)
        {
            Console.WriteLine("$safeitemname$"); // = safeitemname
            Console.WriteLine("$safeprojectname$"); // = safeprojectname
            Console.WriteLine("$ext_safeprojectname$"); // = ext_safeprojectname
            Console.WriteLine("$ext_ext_safeprojectname$"); // = ext_ext_safeprojectname
        }
    }
}

SolutionName\Nested\SubProject1\Class1.cs content (after top project with 'SolutionName' created from template):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace $safeprojectname$
{
    public class Class1
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Class1"); // = safeitemname
            Console.WriteLine("SubProject1"); // = safeprojectname
            Console.WriteLine("Nested"); // = ext_safeprojectname
            Console.WriteLine("SolutionName"); // = ext_ext_safeprojectname
        }
    }
}

Upvotes: 0

Joe Healy
Joe Healy

Reputation: 5817

Try using the Solution Folder element as referenced at https://msdn.microsoft.com/en-us/library/ms171399.aspx . Worked for me using the solution tutorial as referenced by jayway at https://blog.jayway.com/2015/03/13/visual-studio-how-to-create-a-solution-template-with-multiple-projects/ .

Example below:

<?xml version="1.0" encoding="utf-8"?>
<VSTemplate Version="2.0.0" Type="ProjectGroup" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
  <TemplateData>
    <Name>Quotes</Name>
    <Description>WPF Client with a quote engine</Description>
    <ProjectType>CSharp</ProjectType>
    <Icon>Quotes.ico</Icon>
  </TemplateData>
  <TemplateContent>
    <ProjectCollection>
      <SolutionFolder Name="foo">
        <ProjectTemplateLink>
          QuotesLib\QuotesLib.vstemplate
        </ProjectTemplateLink>
      </SolutionFolder>
      <SolutionFolder Name="bar">
      <ProjectTemplateLink>
        WPFPlay\WPFPlay.vstemplate
      </ProjectTemplateLink>
      </SolutionFolder>
    </ProjectCollection>
  </TemplateContent>
</VSTemplate>

Upvotes: 0

Bablu Dutt
Bablu Dutt

Reputation: 359

I did not find a way to do it just by modifying the vstemplate file because the vstemplate's schema was not supporting nested project structure. Hence I found a workaround to do it (not to my liking though). I implemented the IWizard. I zipped the project and added the zip file in the folder structure where I wanted the project to be in. Programatically in the RunFinished method I unzipped the project and added the project into the solution structure.

Upvotes: 1

Related Questions