This article shows you how to rise to the challenge of building an effective page templating scheme. As you will see, combining a Web Control that represents the template to the Web designer with a user control that contains the actual template code, you can achieve an elegant yet simple and reusable approach that's easy to maintain and takes full advantage of the ASP.NET framework. This approach becomes especially important when dealing with complex sites containing large data-driven pages that require page-level customization.
Page Template Methods to Avoid
Many developers have invented ad hoc page templating schemes, with mixed results. The most common approaches are discussed below, along with reasons why you should avoid them.
Classic ASP Method. This method is the most archaic, yet most common way of handling page templating in ASP.NET. Developers create include files, containing header and footer content just as they did in classic ASP. Often, you'll find that heavy use of include files is a side effect of migration. While include files still work, you should avoid using them because the include scheme doesn't take advantage of the ASP.NET framework.
Begin-And-End User Control Method. As developers become more familiar with .NET, they often create two user controls, one for header content and one for footer content, usually named something like
template_begin.ascx and
template_end.ascx. At best, this approach bewilders and confuses the people responsible for page layout, and at worst, it causes errors. Because the opening and closing tags are separated into two files, nesting server-side controls inside the template is not possiblethe ASP.NET runtime doesn't allow this.
Figure 1 shows a screenshot of the errors generated by Visual Studio .NET when trying to do so. In the end this results in treating the user controls as nothing more than glorified include files, which is really no better than the Classic ASP method.
 | |
| Figure 1. The "Begin" Portion of the Begin-and-End Method: The Visual Studio .NET IDE has problems with server control tags that have no closing tag, or are not self-closing. |
Custom Control Method. In this method, developers create a custom server control that encapsulates the entire page. The major drawback to this method is that most developers, following the documentation examples, write the template's HTML content in code, thus negating the whole premise of design and code separation. It's particularly bad in a team environment, with separate designer and programmer roles, because changes to the template require programmers to spend time re-coding the designer's work.
Inherit and Override Render Method. This method has the same drawbacks as the Custom Control method. Unlike the Custom Control method though, all your pages inherit from a common Page class. You override the Render method from each inherited class and provide statements that write out the HTML.
Listing 1 illustrates this method.
Creating a base page class that inherits from the ASP.NET Page class is a good idea; however, inheritance is intended to simplify sharing common code among all the inherited pages. When you use inheritance to override the Render method, you're circumventing the control tree structure. That's fine when your template contains only static HTML, but when you need to include server controls, overriding the Render method quickly becomes confusing. When and where do you declare those server controls? Do you add them to the Page control tree? If you fail to add the server controls to the control tree properly (by overriding the
CreateChildControls() method), the added server controls fail to participate in intrinsic events such as
Init and
Load. Therefore, handlers defined and subscribed to events exposed by these controls never execute. All in all, overriding the Render method by itself does not scale well and is a readability headache.
So if you shouldn't use any of the page templating techniques already described, what should you use? The remainder of this article provides an architecture that you can adapt and extend to your own applications.