Thursday, May 20, 2010

Creating an F# Solution Template for Visual Studio 2010

The title of this post is misleading because you can't actually create a VS2010 solution template (to my knowledge at least).  However, you can create a multi-project template and when I first went looking for how to do this, a search for "how to create a VS2010 solution template" was the first thing that came to mind (apparently many others have done this as well).  Hopefully, this post will make it easier for others to find the information for which they are searching.

In my last post, I provided an F# ASP.NET MVC 2 Web Application template that provides the same functionality as the out of the box C# ASP.NET MVC 2 Web Application template.  In this post, I will show how that template was created.  The full solution including all *.vstemplate and *.vscontent files can be found at http://github.com/dmohl/FSharpMVC2Starter.

Creating the *.vstemplate File for Each Project:


The first step in creating a multi-project template is to create a *.vstemplate file for each of the projects that you wish to include.  This can be accomplished using the export template wizard in visual studio (view the steps on the MSDN web site) or by manually creating the template (view the steps on the MSDN website).

This is what my *.vstemplate file looks like for the FSharpMVC2.Controllers project:
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
  <TemplateData>
    <Name>FSharpMVC2.Controllers</Name>
    <Description>MVC Controllers in F#</Description>
    <ProjectType>FSharp</ProjectType>
    <ProjectSubType>
    </ProjectSubType>
    <SortOrder>1000</SortOrder>
    <CreateNewFolder>true</CreateNewFolder>
    <DefaultName>FSharpMVC2.Controllers</DefaultName>
    <ProvideDefaultName>true</ProvideDefaultName>
    <LocationField>Enabled</LocationField>
    <EnableLocationBrowseButton>true</EnableLocationBrowseButton>
    <Icon>__TemplateIcon.ico</Icon>
  </TemplateData>
  <TemplateContent>
    <Project TargetFileName="FSharpMVC2.Controllers.fsproj" File="FSharpMVC2.Controllers.fsproj" ReplaceParameters="true">
      <ProjectItem ReplaceParameters="false" TargetFileName="HomeController.fs">HomeController.fs</ProjectItem>
      <ProjectItem ReplaceParameters="false" TargetFileName="AccountController.fs">AccountController.fs</ProjectItem>
    </Project>
  </TemplateContent>
</VSTemplate>
The ProjectType element value of "FSharp" specifies that this is an F# template.

Creating the Root *.vstemplate File:

Once the *.vstemplate files have been created, it's time to create a root *.vstemplate.  This looks very similar to the project level *.vstemplate files; however, it references each project level *.vstemplate file rather than the specific project level source/content files.

My root level *.vstemplate file looks like this:
<VSTemplate Version="2.0.0" Type="ProjectGroup"
    xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
    <TemplateData>
        <Name>F# ASP.NET MVC2 Web Application</Name>
        <Description>F# ASP.NET MVC2 Web Application</Description>
        <Icon>__TemplateIcon.ico</Icon>
        <ProjectType>FSharp</ProjectType>
    </TemplateData>
    <TemplateContent>
        <ProjectCollection>
            <ProjectTemplateLink ProjectName="FSharpMVC2.Controllers">
                src\FSharpMVC2.Controllers\MyTemplate.vstemplate
            </ProjectTemplateLink>
            <ProjectTemplateLink ProjectName="FSharpMVC2.Models">
                src\FSharpMVC2.Models\MyTemplate.vstemplate
            </ProjectTemplateLink>
            <ProjectTemplateLink ProjectName="FSharpMVC2.Core">
                src\FSharpMVC2.Core\MyTemplate.vstemplate
            </ProjectTemplateLink>
            <ProjectTemplateLink ProjectName="FSharpMVC2.Web">
                src\FSharpMVC2.Web\MyTemplate.vstemplate
            </ProjectTemplateLink>
        </ProjectCollection>
    </TemplateContent>
</VSTemplate>
Once again, the ProjectType element value of "FSharp" indicates that this is an F# template.

Compresssing the Files:

Once all of the *.vstemplate files are created, it is time to compress all files that are to be included in the template.  To do this, select all the desired items including the root *.vstemplate file, then right-click and choose Send To/Compressed (zipped) Folder.  This will create a single *.zip file.

Creating the Template Installer:

We are now ready to create our template installer.  This involves the creation of one last XML file named *.vscontent.  My FSharpMVC2Template.vscontent file looks like this:
<VSContent xmlns="http://schemas.microsoft.com/developer/vscontent/2005">
    <Content>
        <FileName>FSharpMVC2Template.zip</FileName>
        <DisplayName>F# ASP.NET MVC2 Web Application</DisplayName>
        <Description>F# ASP.NET MVC2 Web Application</Description>
        <FileContentType>VSTemplate</FileContentType>
        <ContentVersion>1.0</ContentVersion>
        <Attributes>
            <Attribute name="ProjectType" value="Visual Web Developer"/>
            <Attribute name="ProjectSubType" value=""/>
            <Attribute name="TemplateType" value="Project"/>
        </Attributes>
    </Content>
</VSContent>
Note: Make sure that the FileName element value matches the name of the compressed file that you made during the "Compressing the Files" step.

Once the *.vscontent file has been created, select it, and the previously created zip file, and compress them into a single zip file. Change the extension of this file to .vsi and you're ready for a test run.

6 comments:

  1. Excellent, been meaning to look into how to do this for a while, but hadn't got round to it yet.

    ReplyDelete
  2. Thanks for the sharing about .Net program. it's really nice. keep it up more post. ASP.Net developers India

    ReplyDelete
  3. Excellent, been meaning to look into how to do this for a while, but hadn't got round to it yet.

    ReplyDelete
  4. The steps to create a web service in VS 2010 is too descriptive easy for a new web application developers to understand and implement. Thanks for sharing. keep up your good work. 

    ReplyDelete
  5. Alfredo Cavalcanti SegundoApril 13, 2012 at 8:05 PM

    Very nice content! Help me a lot!

    ReplyDelete
  6. Is there a way to make sure a different GUID is generated in the "AssemblyInfo.cs" file of each project and for every time someone uses the template ?

    ReplyDelete