使用 HTTP 模块在 Web 应用程序的所有网页中添加页眉和页脚控件






3.21/5 (21投票s)
2004年6月11日
5分钟阅读

118971

1203
使用 HTTP 模块自动为所有 ASP.NET 页面添加页眉和页脚控件。
引言
在开发 Web 应用程序的表示层时,我们通常会为所有网页遵循一个模板结构。该模板通常包含某种公司徽标和导航的页眉部分,以及一些法律信息和联系信息的页脚部分等。这些页眉和页脚部分的 HTML 代码通常在整个站点中是相同的,因此可能需要在每个网页中复制和粘贴。为了避免页眉和页脚部分的 HTML 代码四处复制,我们使用“include
”指令在每个页面中包含一段 HTML 代码。
使用 #Include 指令的问题
然而,正如大多数 Web 开发人员(包括我)已经经历过的那样,这种“include
”方法存在一些缺点。
- 我们需要记住在每个 ASP 页面中插入
include
指令的确切位置。 - 没有逻辑可以对页眉包含文件和页脚包含文件进行分组,如果我们希望为站点的不同部分(例如管理部分、已登录部分和公共部分)拥有多套页眉和页脚,我们最终会得到六个不同的页眉和页脚文件,它们之间完全不相关。
- 我们无法在运行时动态包含不同的文件。
使用控件的替代方法
这个简单的演示说明了一种为 Web 应用程序的所有网页添加页眉和页脚用户控件的替代方法。基本思想是使用 HTTP 模块以编程方式将控件插入到页面中的正确位置。
以下是实现 HTTP 模块的步骤概述
- 创建一个参与页面执行周期的 HTTP 模块。
- 为页面 init 事件注册一个事件处理程序。
- 在页面 init 事件处理程序中,查找“
Form
”控件。 - 实例化页眉和页脚控件,并将其添加到“
Form
”控件中。 - 在 Web.Config 中注册 HTTP 模块。
实现细节
创建 HTTP 模块
要创建 HTTP 模块,我们只需编写一个实现 System.Web.IHttpModule
接口的类。该接口要求实现两个方法:Init
和 Dispose
。通常,在实现 HTTP 模块时,我们会在 Init
方法中注册事件处理程序,以便在 HTTP 请求的处理到达某个阶段时执行它们。在我们的示例中,我们将在处理 HTTP 请求的处理程序实例准备好的阶段注册事件处理程序,即 PreRequestHandlerExecute
事件。
// 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()
{
}
}
为页面 Init 事件注册事件处理程序
当请求处理到达“Pre request handler execute”阶段时,处理程序实例已准备就绪。处理程序可以是任何实现 IHttpHandler
的内容,它可以是网页或一些其他请求处理程序。因此,我们需要过滤掉定向到页面的 HTTP 请求。为此,我们检查请求处理程序的类型,并确保它是一个 HTTP 页面。(稍后,我们可以添加一些其他附加逻辑,用于根据页面类型添加控件)。一旦我们确定处理程序是 Page
对象,我们就需要在其 init
事件中注册另一个事件处理程序,以将控件插入到正确的位置。在页面执行周期中,init
事件是页面控件已初始化的位置。这就是我们定位“Form
”控件并添加其他代码以放置我们自己的页眉和页脚控件的地方,以便它可以在其余的页面执行阶段中使用。要定位 form
控件,我们只需迭代 Page
的 Controls
集合。form
控件应该位于 Page
的 Controls
集合的前几个元素中,因此遍历它们应该不是大问题。
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
}
实现页面 Init 事件处理程序的事件处理程序
在页面 Init 事件处理程序中,我们需要查找“Form
”元素,实例化页眉和页脚控件(使用用户控件 .ascx 文件),并将控件放置在页面中。用于页眉和页脚的控件是使用 Visual Studio .NET 创建的用户控件。这包括一个 ascx 文件和一个代码隐藏文件。您可以在用户控件中放入其他服务器控件,例如登录按钮,并将处理登录按钮单击的代码放在用户控件的代码隐藏中。
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;
}
}
}
在 web.config 文件中注册模块
要注册 HTTP 模块,只需在 web.config 文件的 system.web
元素中添加以下配置段:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.web> <httpModules> <add name="HeaderFooterModule" type="MyNamespace.HeaderFooterModule,MyAssembly"/> </httpModules> </system.web> </configuration>
变奏
对于具有不同部分(例如管理部分和公共页面部分)的站点,我们可能希望使用不同的页眉和页脚设计。在这种情况下,一种可能的方案是让这些部分中的页面实现不同的标记接口。标记接口基本上是一个没有定义任何方法的接口。如果您只是想识别页面是否属于某个特定类别,它特别有用。例如,我们可以将上面的 Page_Init
处理程序实现替换为以下代码,以便它检查页面类型并确定要使用的适当的页眉和页脚 ascx 文件:
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;
}
}
}
对于管理页面的代码隐藏类
public interface IAdminPage {
}
public class HeaderFooterModule : Page, IAdminPage{
...
}
关于以编程方式向页面添加控件的特别说明
需要注意的是,使用这种方法,您不能直接在 ASP.NET 页面中编写代码片段。虽然这可能引起一些人的担忧,但我认为这并不是一个大问题,因为我相信大多数代码片段都可以被控件替代。
结论
通过这种使用 HTTP 模块添加页眉和页脚控件的方法,我们可以实现以下目标:
- 在不修改 ASP.NET 页面的任何内容的情况下,为所有页面添加统一的页眉和页脚。
- 可以为不同的部分拥有不同套的页眉和页脚。所有页面只需要实现适当的标记接口。
- 能够修改模块以添加额外的逻辑(例如基于用户凭据...)来实例化和插入不同的页眉/页脚控件。