Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Add a header and footer control to all web pages in a web application, using HTTP module

0.00/5 (No votes)
2 Aug 2004 1  
Use the HTTP module to automatically add a header and footer control to all ASP.NET pages.

Introduction

When developing the presentation of a web application, we typically follow a template structure for all the web pages. The template usually contains some sort of company logo and navigation in a header section, and some legal info and contact info in the footer section, etc. The HTML codes for these header and footer section are typically the same throughout the entire site, and may therefore need to be copied and pasted in every single web page. To avoid the HTML code for the header and footer section being replicated all over the place, we use the "include" directive to include a chunk of HTML code in every page.

Problem with using #Include Directive

There are however some drawbacks with this "include" approach as most of the web developers, including me, have already experienced:

  1. We need to remember the exact location in every single ASP page to insert the include directives.
  2. There is no logic to group the header include file and footer include file, and if we ever need to have multiple sets of headers and footers for different sections of the site, such as an admin section, an authenticated section, and a public section, we end up having six different header and footer files sitting around that are totally unrelated to each other.
  3. We can't really dynamically include different files during runtime.

Alternative Approach using Controls

This simple demonstration illustrates an alternative way of adding a header and footer user control to all web pages in your web application. The general idea is to use a HTTP module to insert the controls programmatically in the right location in the page.

Here's an outline of the steps for implementing the HTTP module:

  1. Create an HTTP module that will participate in the page execution cycle.
  2. Register an event handler for the page init event.
  3. In the page init event handler, look for the "Form" control.
  4. Instantiate the header and footer control and add it to the "Form" control.
  5. Register the HTTP Module in the Web.Config.

Implementation details

Create an HTTP module

To create an HTTP module, we simply write a class that implements the System.Web.IHttpModule interface. The interface requires two methods to be implemented: Init and Dispose. Typically, when implementing a HTTP Module, we will register event handlers in the Init method so that they get executed when the processing of the HTTP request reaches a certain stage. In our example, we will register the event handler at the stage when the instance of the handler for the HTTP request is ready, namely, the PreRequestHandlerExecute event.

// Note: Make sure you have the following namespace included in your

// code:

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
-----------------------------------------
public class HeaderFooterModule : IHttpModule{

    public HeaderFooterModule()
    {
    }

    public void Init(HttpApplication context)
    {
        //Register the event handler for PreRequestHandlerExecute event in 

        //the HTTP Request handling cycle

        context.PreRequestHandlerExecute += 
                   new EventHandler(context_PreRequestHandlerExecute);
    }

    private void context_PreRequestHandlerExecute(object sender, EventArgs e)
    {
        //See next code block for implementation of this handler        

    }

    public void Dispose()
    {
    }
}

Register an Event Handler for the Page Init event

When the Request handling reaches the stage of "Pre request handler execute", the handler instance is ready. The handler can be anything that implements IHttpHandler, this could be a web page or some other Request handlers. Therefore, we need to filter out the HTTP Request directed to a page. To do this, we check the type of the request handler and make sure it's a HTTP page. (Later on, we can add some other additional logic for adding control based on the page type). Once we determine that the handler is a Page object, we need to register another event handler in its init event to insert the control in the right location. In a page execution cycle, the init event is where the page has its controls initiated. This is where we locate the "Form" control and put additional code to place our own header and footer controls so that it will become available for the rest of the page execution stages. To locate the form control, we use a simple iteration of the Page's Controls collection. The form control should be within the first few elements in the Page's Controls collection, so iterating through them shouldn't be a big problem.

    private void context_PreRequestHandlerExecute(object sender, EventArgs e)
    {
        //Get the Request handler from the Context

        HttpContext oContext = ((HttpApplication)sender).Context;
        //Check if the request handler is a Page object

        if (oContext.Handler is Page)
        { 
            Page objPage = (Page)oContext.Handler;
            //Register an event handler for the page init event            

            objPage.Init += new EventHandler(Page_Init);
        }        
    }

    private void Page_Init(object sender, EventArgs e)
    {
        //See next code block for implementation of this handler        

    }

Implement the event handler for the Page init event handler

In the page init event handler, we will need to look for the "Form" element, instantiate the header and footer controls (using a user control .ascx file), and place the controls in the page. The controls we use for the header and footer are user controls created using Visual Studio .NET. This includes an ascx file and a code behind. You can put other server controls in your user control such as a login button, and put the code that handles the login button click in the code behind of the user control.

    private void Page_Init(object sender, EventArgs e)
    {
        //Iterate through the control collection for the page

        foreach (Control objControl in ((Page)sender).Controls) 
        {
            if (objControl is HtmlForm) 
            {
                HtmlForm objForm = (HtmlForm)objControl;
                //Instantiate and add the control to the page 

                //using the .ASCX file

                objForm.Controls.AddAt(0, 
                    objForm.Page.LoadControl("Header.ascx"));
                objForm.Controls.Add(objForm.Page.LoadControl("Footer.ascx"));
                break;
            }
        }
    }

Registering the module in the web.config file

To register an HTTP module, simply add the following config segment in the system.web element of the web.config file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <httpModules>
      <add name="HeaderFooterModule" 
           type="MyNamespace.HeaderFooterModule,MyAssembly"/>
    </httpModules>
  </system.web>
</configuration>

Variations

For sites with different sections, such as an admin section and a public page section, we might want to use different header and footer design. For this case, one possible scenario is to have these pages in these two different sections implement different tag interface. A tag interface is basically an interface with no method defined in it. It's particularly useful if you simply want to identify is a page is of a certain category. For example, we can replace the Page_Init handler implementation above with the following code so that it checks for the page type and determines the appropriate header and footer ascx files to use:

private void Page_Init(object sender, EventArgs e)
{
  //Iterate through the control collection for the page

  foreach (Control objControl in ((Page)sender).Controls) 
  {
    if (objControl is HtmlForm) 
    {
      HtmlForm objForm = (HtmlForm)objControl;
      if (sender is IAdminPage) 
      {
        //Instantiate and add the admin control to the page using 

        //the .ASCX file

        objForm.Controls.AddAt(0, 
          objForm.Page.LoadControl("AdminHeader.ascx"));
        objForm.Controls.Add(objForm.Page.LoadControl("AdminFooter.ascx"));
      }
      else
      {
        //Instantiate and add the regular control to the page 

        //using the .ASCX file

        objForm.Controls.AddAt(0,objForm.Page.LoadControl("Header.ascx"));
        objForm.Controls.Add(objForm.Page.LoadControl("Footer.ascx"));
      }    
      break;
    }
  }
}

For the code behind class for admin page:

public interface IAdminPage {
}
public class HeaderFooterModule : Page, IAdminPage{
    ...
}

Special note about programmatically adding control to a page

It should be noted that with this approach, you cannot write code snippets inside the ASP.NET page directly. While this might be a concern to some people, I don't find it too much of an issue because I believe most of the snippets can be replaced by controls.

Conclusion

With this approach of adding header and footer controls using a HTTP Module, we are able to achieve the following:

  1. Add a uniform header and footer to all pages without modifying anything in the ASP.NET page.
  2. Can have different sets of header and footer for different sections. All the page has to do is to implement the appropriate tag interface.
  3. Able to modify the module to put additional logic (such as based on the user credential...) to instantiate and insert different header/footer controls.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here