You are not currently logged in.  Please Log in or Register.

Master Pages in ASP.NET v. 1.1

Wednesday, June 08, 2005
12:26 AM

This article has been accessed 332 times.

One of the basic precepts of professional Web design is to keep a consistent color scheme and layout. With CSS, keeping a consistent color scheme is easy and although creating a consistent layout is possible, it is often difficult to achieve due to differences in browser implementations of CSS as well as forcing UI designers to name individual elements in a specific manner and implement a variety of CSS classes. In today's world, it is often more effective to utilize an HTML based solution for tackling layout issues.

ASP.NET 2.0 provides Master Pages to address creating a consistent layout for a Web site. While Master Pages are a welcome addition to the .NET Framework, many .NET developers will not be migrating to v. 2.0 immediately because of investments in v. 1.1. Unfortunately, Master Pages are not available in v. 1.1 but hope is not lost.

By taking advantage of the concepts that ASP.NET is built upon, one can easily achieve an equivalent effect in v. 1.1 by following a few easy steps.

  1. Creating the layout
  2. Define a base Page class
  3. Create the Content

Before moving on, it is important to know that this article has been written assuming that Visual Studio.NET 2003 is being used and the code examples are in C# but converting to VB should be a pretty routine task. For the purpose of these examples, assume that all code is in the MasterPageExample namespace. The complete code is available for download at the end of this article. The examples in this article also take advantage of inheritance, polymorphism, and casting so if you are unfamiliar with these concepts, you may want to read my introduction.

Creating the layout

The layout (template) will be defined in a User Control. Create the template as you would create any other User Control. Typically, the template will contain the page header, navigation, and footer. If the header and navigation are already been defined in User Controls, don't fret, the controls may be used here too.

The most important part of creating the template is defining a place to hold the page content. If you haven't guessed, the easiest way to do this is with a PlaceHolder although other methods may be used depending on your layout.

[Template Example - Template.ascx]
<p align="center">[Header - Site Title, Logo, Etc...]</p>
<p align="center">[Navigation]</p>
<asp:placeholder id="PageContent" runat="server" />
<p align="center">[Footer - Copyright, Contact Info, Etc...]</p>

Note that the template does not define the HTML, HEAD, and BODY elements. These elements will be defined by the individual pages.

Define a Base Page Class

The easiest way to create the base page class is to start from an empty class. The base page class will need to override OnInit() and include a method for locating the FORM element inside of each derived page. At a minimum, you should import the following namespaces although your solution may require others.

  • System
  • System.Web
  • System.Web.UI
  • System.Web.UI.HtmlControls
  • System.Web.UI.WebControls

The OnInit() method will be responsible for adding the template to the page and moving the page content into the PlaceHolder that is defined on the template.

[C# Base Page Example]
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

namespace MasterPageExample
{
  public class PageBase : System.Web.UI.Page
  {
    protected override void OnInit(EventArgs e)
    {
      HtmlForm pageForm = FindForm(Page.Controls);

      if(pageForm == null)
        throw new ApplicationException("Page must contain a form!");

      // This line assumes that your template file name is Template.ascx
      // It could be replaced to read from the web.config file
      UserControl template = (UserControl)LoadControl(
        HttpContext.Current.Request.ApplicationPath + "/Template.ascx");
      
      pageForm.Controls.AddAt(0, template);
      
      // Obtain a reference to the template's content place holder.  If a type
      // other than PlaceHolder is used, the type name should be replaced
      // accordingly.  This also assumes that the name of the control is
      // "PageContent"
      PlaceHolder content = (PlaceHolder)template.FindControl("PageContent");

      if(content == null)
        throw new ApplicationException("Could Not Find Place Holder!");

      // Add the page content to the template
      while(pageForm.Controls.Count > 1)
        content.Controls.Add(pageForm.Controls[1]);

      base.OnInit(e);
    }

    private HtmlForm FindForm(ControlCollection controls)
    {
      HtmlForm frm = null;

      foreach(Control ctrl in controls)
      {
        if(ctrl is HtmlForm)
        {
          frm = (ctrl as HtmlForm);
          break;
        }
        else if(ctrl.HasControls())
        {
          frm = FindForm(ctrl.Controls);
          if(frm != null)
            break;
        }
      }

      return frm;
    }
  }
}

An item of importance in the code example is the call to content.Controls.Add(). An interesting side effect of this call is that the parent item of the control passed as the parameter is actually changed to the PlaceHolder; the form control is actually being moved from the form into the PlaceHolder. It is important to use form.Controls[1] rather than form.Controls[0] because item 0 is the template.

Create The Content

Creating the content is also a straight forward task. To create the content, simply create a new Web form and start typing! There is only one other task required to force the page to use the template defined in step one. Open the code-behind for the Web Form and replace "System.Web.UI.Page" with the name of the template:

[C#]
public class MyPage : PageBase
{
  //
  // Page code
  //
}

[Content]
<p align="center"
  style="text-align: center; text-transform: uppercase;
    font-weight: bold; text-decoration: underline;">
  ASP.NET 1.1 Master Page Example
</p>

After changing the base type for the page, compile and run the project (make sure you have selected the startup page) and, if all has been written correctly, the page will load with the content moved into the template. This works because the page (MyPage) derives from our PageBase. PageBase.OnInit() locates the page's Form and inserts the template control at item zero. It then moves all of the controls from the form (with index > 1) into the PlaceHolder contained in the template.

Conclusion

This example is simple but shows how to take advantage of an ASP.NET 2.0 concept in an ASP.NET 1.1 application although we do not have the "friendly" XML syntax that Master Pages use. Master Pages also provide some additional functionality such as Child Master Pages and programatic access to Master Page objects but the example should be fairly easy to extend to support these concept as well. Another difference between this example and ASP.NET 2.0 Master Pages is that in Master Pages, the general HTML tags (HTML, HEAD, BODY, etc...) are defined in the Master Page rather than in each page.

Using this code, those that will not implement 2.0 immediately can already take advantage of the concept.

Download [MasterPageExample.ZIP ~16K]


Rate This Article
Overall Rating:  Not Rated My Rating: 


Comments

Be the first to comment on this article!

Name Anonymous Poster [Login]
Comment
 

Tags: