Click here to Skip to main content
15,881,173 members
Articles / Web Development / ASP.NET

Introducing ASP.NET Page Modules

Rate me:
Please Sign up or sign in to vote.
3.81/5 (10 votes)
15 Apr 2010CPOL3 min read 57.3K   360   48   10
This article introduces the concept of Page Modules, which are similar to HTTP Modules but related to Page Life Cycle, and the need for them.

(Republished from http://msmvps.com/blogs/paulomorgado/pages/introducing-asp-net-page-modules.aspx.)

Introduction

This article introduces the concept of Page Modules, which are similar to HTTP Modules but related to Page Life Cycle, and the need for them.

How HTTP Modules Work

According to the documentation, using an HTTP Module, "enables you to redirect the request to an alternative page, modify the request, or perform any other request manipulation". Well, at least up until you call Server.Transfer or Server.Execute, then you lose all the ability to tap into the Page Life Cycle of the served page.

How Page Modules Work

Page Modules enable you to handle every event in the Page Life Cycle of any page as well as its creation and release.

Each Page Module has an Init method that is called when the Page Handler Factory with Modules is initialized, and each Page Module can subscribe to two events: PageCreated and PageReleasing.

In the PageCreated event arguments, there are properties that expose the Page being created, the Context of the HTTP request, the HTTP data transfer method (GET or POST) that the client uses, the virtual path to the requested resource, and the physical application path of the requested page. Using the reference to the page being created, you can subscribe to all events in the Page Life Cycle of the page being created.

In the PageReleasing event arguments, there is a property that exposes the Page being released.

Page Modules versus HTTP Modules

You can implement much of the functionality of a Page Module as an HTTP Module if you are not calling Server.Transfer or Server.Execute. However, if you are using frameworks or application blocks like the Web Client Software Factory and its Page Flow Application Block that heavily rely on client redirects, you can greatly reduce network usage and server load by using a Page Module instead of an HTTP Module, at least, for part of its work.

Implementation of the Page Handler Factory with Modules

The implementation of PageHandlerFactoryWithModules relies solely on sub-classing the PageHandlerFactory class and exposing events corresponding to the two methods of the IHttpHandlerFactory interface (GetHandler and ReleaseHandler).

C#
public class PageHandlerFactoryWithModules : System.Web.UI.PageHandlerFactory
{
    // ...

    public sealed override IHttpHandler GetHandler(HttpContext context, 
           string requestType, string virtualPath, string path)
    {
        Page page = base.GetHandler(context, requestType, virtualPath, path) as Page;

        if (page != null)
        {
            OnPageCreated(new PageCreatedEventArgs(page, context, 
                          requestType, virtualPath, path));
        }

        return page;
    }

    public sealed override void ReleaseHandler(IHttpHandler handler)
    {
        Page page = handler as Page;

        OnPageReleasing(new PageEventArgs(page));

        base.ReleaseHandler(page);
    }

    // ...
}

As you can see, the PageHandlerFactoryWithModules class seals the GetHandler and ReleaseHandler methods, and in replacement, exposes the OnPageCreated and OnPageReleasing that are responsible for triggering the PageCreated and PageReleasing events.

C#
public class PageHandlerFactoryWithModules : System.Web.UI.PageHandlerFactory
{
    // ...

    protected virtual void OnPageCreated(PageCreatedEventArgs pageEventArgs)
    {
        TriggerEvent(pageCreatedEvent, pageEventArgs);
    }

    protected virtual void OnPageReleasing(PageEventArgs pageEventArgs)
    {
        TriggerEvent(pageReleasingEvent, pageEventArgs);
    }

    // ...
}

On initialization of the PageHandlerFactoryWithModules class, all modules are created from the configuration information and initialized.

C#
public class PageHandlerFactoryWithModules : System.Web.UI.PageHandlerFactory
{
    // ...

    public PageHandlerFactoryWithModules()
    {
        // ...

        InitModules();
    }

    private void InitModules()
    {
        PageModulesSection section = 
          WebConfigurationManager.GetWebApplicationSection("PauloMorgado.web/pageModules") 
          as PageModulesSection;

        this.modules = section.CreateModules();

        foreach (IPageModule module in this.modules)
        {
            module.Init(this);
        }
    }

    // ...
}

As you can infer from the previous code block, a Page Module is a class that implements the IPageModule interface which has only one method called Init that receives a reference to the PageHandlerFactoryWithModules instance, just like with HTTP Modules.

C#
public interface IPageModule
{
    void Init(PageHandlerFactoryWithModules context);
}

(The full implementation of the Page Module concept is in the attached code download.)

How to: Create Custom Page Modules

The custom page module described in this section subscribes to the PreInit event of the page being created to change its master page.

Creating the Custom Page Module Class

To implement a custom page module, all you have to do is create a class that implements the IPageMoldule interface and handle the required events.

In the current example, the module needs to subscribe to the PreInit event of the page being created, and in the event handler method, changes the master page if the page has one.

C#
public class MasterModule : IPageModule
{
    public MasterModule()
    {
    }

    public void Init(PageHandlerFactoryWithModules context)
    {
        context.PageCreated += PageCreatedHandler;
    }

    private static void PageCreatedHandler(object sender, 
                   PauloMorgado.Web.UI.PageEventArgs e)
    {
        e.Page.PreInit += PagePreInit;
    }

    private static void PagePreInit(object sender, EventArgs e)
    {
        Page page = (sender as Page);

        if (page.MasterPageFile != null)
        {
            page.MasterPageFile = "~/Site.master";
        }
    }
}

Registering the Custom Page Module

To register the page module, you'll need to add the PauloMorgado.web configuration section group and its inner pageModules configuration section.

Then, you'll have to remove the default declaration for the *.aspx path and add the PageHandlerFactoryWithModules class as the new *.aspx handler factory.

Finally, you can add your page modules in the configuration/PauloMorgado.web/pageModules configuration section.

XML
<?xml version="1.0"?>
<configuration>
    <configSections>
        <sectionGroup name="PauloMorgado.web">
            <section name="pageModules"
                     type="PauloMorgado.Web.Configuration.PageModulesSection, 
                           PauloMorgado.Web.UI.PageHandlerFactoryWithModules"/>
        </sectionGroup>
    </configSections>
    <system.web>
        <httpHandlers>
            <remove verb="*" path="*.aspx"/>
            <add verb="*" path="*.aspx" validate="false"
                 type="PauloMorgado.Web.UI.PageHandlerFactoryWithModules, 
                        PauloMorgado.Web.UI.PageHandlerFactoryWithModules"/>
        </httpHandlers>
    </system.web>
    <PauloMorgado.web>
        <pageModules>
            <add name="MasterModule" type="MasterModule"/>
        </pageModules>
    </PauloMorgado.web>
</configuration>

Testing the Custom Page Module

In the attached code download, there's a sample of the master page changing module implemented as a page module and as an HTTP module.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Paulo Morgado
Portugal Portugal

Comments and Discussions

 
Generalgood post. Pin
Shahriar Iqbal Chowdhury/Galib18-Apr-10 21:21
professionalShahriar Iqbal Chowdhury/Galib18-Apr-10 21:21 
GeneralRe: good post. Pin
Paulo Morgado18-Apr-10 22:19
professionalPaulo Morgado18-Apr-10 22:19 
GeneralNice work Pin
paul.vencill15-Apr-10 18:46
paul.vencill15-Apr-10 18:46 
GeneralRe: Nice work Pin
Paulo Morgado15-Apr-10 22:46
professionalPaulo Morgado15-Apr-10 22:46 
Generalplease humour a newbie Pin
germgerm11-Sep-07 4:33
germgerm11-Sep-07 4:33 
GeneralRe: please humour a newbie Pin
Paulo Morgado11-Sep-07 14:36
professionalPaulo Morgado11-Sep-07 14:36 
GeneralRe: please humour a newbie Pin
germgerm13-Sep-07 3:32
germgerm13-Sep-07 3:32 
GeneralRe: please humour a newbie Pin
Paulo Morgado13-Sep-07 3:41
professionalPaulo Morgado13-Sep-07 3:41 
QuestionWhy not post the whole article? Pin
Drew Stainton9-Sep-07 19:20
Drew Stainton9-Sep-07 19:20 
AnswerRe: Why not post the whole article? Pin
Paulo Morgado9-Sep-07 21:37
professionalPaulo Morgado9-Sep-07 21:37 
I'm sorry if it looks like that. It was due to time constraints. I hope to publish the whole article later today.

Paulo Morgado
Portugal - Europe's West Coast

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.