65.9K
CodeProject 正在变化。 阅读更多。
Home

Introducing ASP.NET Page Modules

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.81/5 (10投票s)

2007年9月9日

CPOL

3分钟阅读

viewsIcon

58867

downloadIcon

372

本文介绍了 Page Modules 的概念,它类似于 HTTP Modules,但与 Page Life Cycle 相关,并阐述了其必要性。

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

引言

本文介绍了 Page Modules 的概念,它类似于 HTTP Modules,但与 Page Life Cycle 相关,并阐述了其必要性。

HTTP Modules 如何工作

根据文档,使用 HTTP Module,“使您能够将请求重定向到另一个页面,修改请求,或执行任何其他请求操作”。然而,直到调用 Server.TransferServer.Execute 之后,您将失去所有利用所提供页面的 Page Life Cycle 的能力。

Page Modules 如何工作

Page Modules 使您能够处理 Page Life Cycle 中每个页面的所有事件,以及其 创建释放

每个 Page Module 都有一个 Init 方法,在初始化 Page Handler Factory with Modules 时被调用,并且每个 Page Module 可以订阅两个事件:PageCreatedPageReleasing

PageCreated 事件参数中,有一些属性可以公开正在创建的 Page、HTTP 请求的 Context、客户端使用的 HTTP 数据传输方法(GET 或 POST)、请求资源的虚拟路径以及请求页面的 物理应用程序路径。通过对正在创建的页面的引用,您可以订阅正在创建的页面的 Page Life Cycle 中的所有事件。

PageReleasing 事件参数中,有一个属性可以公开正在释放的 Page

Page Modules 与 HTTP Modules 的区别

如果您没有调用 Server.TransferServer.Execute,则可以使用 HTTP Module 来实现 Page Module 的大部分功能。然而,如果您正在使用像 Web Client Software Factory 及其 Page Flow Application Block 这样严重依赖客户端重定向的框架或应用程序块,那么通过使用 Page Module 而不是 HTTP Module,可以大大减少网络使用量和服务器负载,至少是其部分工作。

Page Handler Factory with Modules 的实现

PageHandlerFactoryWithModules 的实现完全依赖于继承 PageHandlerFactory 并公开对应于 IHttpHandlerFactory 接口 的两个方法的事件(GetHandlerReleaseHandler)。

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);
    }

    // ...
}

如您所见,PageHandlerFactoryWithModules 类密封了 GetHandlerReleaseHandler 方法,取而代之的是公开了 OnPageCreatedOnPageReleasing,它们负责触发 PageCreatedPageReleasing 事件。

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);
    }

    // ...
}

在初始化 PageHandlerFactoryWithModules 类时,所有模块都将从配置信息中创建并初始化。

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);
        }
    }

    // ...
}

正如您从前面的代码块中可以推断出的,Page Module 是一个实现 IPageModule 接口的类,该接口只有一个名为 Init 的方法,它接收一个指向 PageHandlerFactoryWithModules 实例的引用,这与 HTTP Modules 类似。

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

(Page Module 概念的完整实现请参见 附加的代码下载)。

如何:创建自定义 Page Modules

本节描述的自定义页面模块订阅正在创建的页面的 PreInit 事件 以更改其 主控页

创建自定义 Page Module 类

要实现自定义页面模块,您只需要创建一个实现 IPageMoldule 接口并处理所需事件的类。

在当前示例中,模块需要订阅正在创建页面的 PreInit 事件,并在事件处理程序方法中,如果页面有主控页,则更改 主控页

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";
        }
    }
}

注册自定义 Page Module

要注册页面模块,您需要添加 PauloMorgado.web 配置节组及其内部的 pageModules 配置节。

然后,您需要删除 *.aspx 路径的默认声明,并将 PageHandlerFactoryWithModules 类添加为新的 *.aspx 处理程序工厂。

最后,您可以在 configuration/PauloMorgado.web/pageModules 配置节中添加您的页面模块。

<?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>

测试自定义 Page Module

附加的代码下载 中,有一个示例,其中主控页更改模块既实现了 page module,也实现了 http module。

© . All rights reserved.