Creating Custom Page Templates with Unique Code Behind Classes in Visual Web Developer Express or Visual Studio

Visual Studio (2005 and later) has a nice feature to create your own templates that appear in the Add New Item dialog of a web site. This feature enables you to create new files, such as a Web Form, to your liking and then export it as a template so you can base new items on it.

Exporting a Template

Creating and exporting a template is super easy: just create a new file (a Web Form or another type you'd like to template such as a User Control), add any content you see fit, choose File | Export Template and follow the on-screen instructions. You can make the template more reusable by modifying the code and adding template replacement parameters before you export it. The parameters will be replaced with real values when an item based on the template is added to the project or site. For example, to create a reusable Web Form, you can change the Code Behind class and the Inherits attribute of the page directive to $safeitemname$ before you export the template, like this:

<%@ Page Language="C#" AutoEventWireup="true" 
            CodeFile="Default.aspx.cs" Inherits="$safeitemname$"

...

public partial class $safeitemname$ : System.Web.UI.Page 
{
  protected void Page_Load(object sender, EventArgs e)
  {

  }
}

When you export the template (using File | Export Template) and then create a new item based on that template, the $safeitemname$ placeholder is replaced with the file name you enter in the Add New Item dialog. So if you enter MyTestPage.aspx as the new page name, you end up with a Code behind class called MyTestPage. So far so good; I've been using this method since the Export Template feature was introduced in Visual Studio 2005. I also included instructions about creating the template based on this technique in my book Beginning ASP.NET 3.5 in C# and VB. However, recently a reader pointed out a potential issue with this setup: when you have multiple pages with the same name (say, Default.aspx) in different folders, you can end up with duplicate class names which may get you into troubles when you precompile your web application using deployment tools.

Visual Web Developer itself is able to create correct class names when adding files (by following a FolderName_FileName scheme) so there had to be a way to fix it. I searched the web for it and found nothing. I finally got the answer from Bill Hiebert from the Visual Web Developer team:

You can do this by changing your template to use "$relurlnamespace$_$safeitemname$" rather than just $safeitemname$. The only downside is that if your template is added to the root of the web, the class will have a leading underscore. We work around this by associating a wizard with our template that creates a new variable (replaceable parameter) called $codebesideclassname$. Unfortunately, our wizard has some code which is specific to our template and is not generally usable by yours.


 

To implement this, you need to make the following changes:

<%@ Page Language="C#" AutoEventWireup="true" 
            CodeFile="Default.aspx.cs" Inherits="$relurlnamespace$_$safeitemname$"

...

public partial class $relurlnamespace$_$safeitemname$ : System.Web.UI.Page 
{
  protected void Page_Load(object sender, EventArgs e)
  {

  }
}

Now, when you create a file in, say, the About folder you get the following, unqiue code behind class:

public partial class About_Default : System.Web.UI.Page 
{
  protected void Page_Load(object sender, EventArgs e)
  {
  }
}

The template replacement parameter is currently undocumented on the Template Parameters page at the MSDN site, but that might change in the future.

Happy templating!


Where to Next?

Wonder where to go next? You can read existing comments below or you can post a comment yourself on this article .


Consider making a donation
Please consider making a donation using PayPal. Your donation helps me to pay the bills so I can keep running Imar.Spaanjaars.Com, providing fresh content as often as possible.



Feedback by Other Visitors of Imar.Spaanjaars.Com

On Thursday, September 09, 2010 11:51:03 AM Kenji Obara said:
This article was very usefull! Thx!
On Friday, May 04, 2012 7:33:20 PM M.Mattei said:
Thank You Imaar! I looked around a lot for this since in Web Site Project there is no "auto-namespace" option, so this is the only way.
I found a way to overcome the "being in the root" problem.
Even if it's not documented you can use conditional expression in templates. Also I "hacked" a workaround to check if the $relurlnamespace$ is empty (being in the root)
The final code looks something like:
$if$ ($relurlnamespace$ != $emptystring$)line with full path$else$line without the $relurlnamespace$ parameter$end if$

You have to declare the $emptystring$ as a custom parameter in the template metadata file like this:
  [TemplateContent]
    [CustomParameters]
        [CustomParameter Name="$EmptyString$" Value=""/]
    [/CustomParameters]
  [/TemplateContent]

(replace brackets with the correct xml opening and closing tags)

This addition to your post is my way to say again thank you!
On Saturday, May 05, 2012 7:25:47 AM Imar Spaanjaars said:
Hi M.Mattei,

Thanks for that; very useful.

Cheers,

Imar

Talk Back! Comment on Imar.Spaanjaars.Com

I am interested in what you have to say about this article. Feel free to post any comments, remarks or questions you may have about this article. The Talk Back feature is not meant for technical questions that are not directly related to this article. So, a post like "Hey, can you tell me how I can upload files to a MySQL database in PHP?" is likely to be removed. Also spam and unrealistic job offers will be deleted immediately.

When you post a comment, you have to provide your name and the comment. Your e-mail address is optional and you only need to provide it if you want me to contact you. It will not be displayed along with your comment. I got sick and tired of the comment spam I was receiving, so I have protected this page with a simple calculation exercise. This means that if you want to leave a comment, you'll need to complete the calculation before you hit the Post Comment button.

If you want to object to a comment made by another visitor, be sure to contact me and I'll look into it ASAP. Don't forget to mention the page link, or the QuickDocId of the document.

For more information about the Talk Back feature, check out this news item.