ASP.NET 实践:HTTP 模块的创建与配置

本文描述了如何使用 HttpModulesSection 类和其他相关类型对 Web 应用程序配置中的 httpModules 元素配置进行编程。

一个 HTTP 模块是一个实现了 IHttpModule 接口并通过为应用程序事件提供处理过程的方式来为请求提供相应的处理类型。

下面的部分包括一个实例 HTTP 模块和一个通过编程对 ASP.NET Web 应用程序的 HTTP 模块进行添加或删除的实例代码。这些实例中的 HTTP 模块 RequestTimeIntervalModule.dll 是一个简单的库应用。RequestTimeIntervalModule 类成员用于对 Web 请求开始和结束之间的时间间隔进行计算,并获得主要 ID,最后在应用程序中的任何一个网页中显示相关信息。

HTTP 模块实例

这个代码实例演示了如何实现一个 HTTP 模块。

下例代码实例说明了一个完整的 HTTP 模块,该模块被编写成单独的已编译汇编集 Samples.Aspnet.HttpModuleExamples。如果你对这个汇编集进行编译,那么 DLL 文件必须保存到 ASP.NET 应用程序的 Bin 目录中,或者你也可以把它添加到全局汇编缓存中。

另外,你可以把源代码文件保存到 ASP.NET 应用程序的 App_Code 目录中。关于如何使用这类实现的实例,请参考“创建自定义 HTTP 模块”。关于编译选项的更多信息,请参考“ASP.NET 编译模型”。

在你为 ASP.NET 应用程序添加了 HTTP 模块并且对它进行手动配置或者通过使用“HTTP 模块的配置代码实例”中的代码进行配置之后,任何一个对 ASP.NET 内容的请求都将会显示下列模块消息:


当前用户:<用户名称>

请求开始事件和请求结束事件之间的时间间隔:<时间间隔>

你的友好 HttpModule:RequestTimeIntervalModule


using System;

using System.Collections.Generic;

using System.Text;

using System.Web;

using System.Security.Principal;



namespace Samples.Aspnet.HttpModuleExamples

{

    public class RequestTimeIntervalModule : IHttpModule

    {

        public void Dispose()

        {

        }



        // 添加 HttpApplication 的事件处理器。

        public void Init(HttpApplication httpApp)

        {

            httpApp.BeginRequest += new EventHandler(OnBeginRequest);

            httpApp.EndRequest += new EventHandler(OnEndRequest);

        }



        // 记录请求开始事件的时间。

        public void OnBeginRequest(Object sender, EventArgs e)

        {

            HttpApplication httpApp = (HttpApplication)sender;

            httpApp.Context.Items["beginRequestTime"] = DateTime.Now;

        }



        public void OnEndRequest(Object sender, EventArgs e)

        {

            HttpApplication httpApp = (HttpApplication)sender;

            

            // 获得请求开始事件的时间。

            DateTime beginRequestTime =

                (DateTime)httpApp.Context.Items["beginRequestTime"];

            

            // 计算请求开始事件和请求结束事件之间的时间间隔。

            TimeSpan ts = DateTime.Now - beginRequestTime;

            

            // 把时间间隔作为请求头进行输出。

            httpApp.Context.Response.AppendHeader("TimeSpan", ts.ToString());

            

            // 获得当前用户的 ID。

            string user = WindowsIdentity.GetCurrent().Name;



            // 在页面中显示信息。

            StringBuilder sb = new StringBuilder();

            sb.AppendLine("<H2>RequestTimeInterval HTTP 模块输出</H2>");

            sb.AppendFormat("当前用户: {0}<br/>", user);

            sb.AppendFormat("请求开始事件和请求结束事件之间的时间间隔:{0}<br/>", 

                ts.ToString());



            httpApp.Context.Response.Output.WriteLine(sb.ToString());



        }



    }

}

HTTP 模块代码实例的配置

这个代码实例演示的网页中包含了用于 HTTP 模块配置的代码。关于实例中如何使用页面链接到其他文件的详细信息,请参考“ASP.NET 实践:HTTP 模块的创建和配置”。

下例代码实例完成了这些动作:

  • 对 ASP.NET 应用程序 /Temp 中现有的已配置 HTTP 模块进行列举。

  • 对 HTTP 模块 RequestTimeIntervalModule 进行测试,以检测是否已经对配置进行设定。要查看该模块的代码,请参考上述代码实例。

  • 为任何一个已经存在的设定提供选项。

  • 如果 HTTP 模块 RequestTimeIntervalModule 不存在相关设定,则会自动创建。

新的 HTTP 模块 RequestTimeIntervalModule 会创建一个 HttpModuleAction 对象。该对象用于第一次添加新的配置设定。构造器中第二个参数的格式是 类型名称[, 汇编集名称]。如果你的 HTTP 模块已经被编译成 DLL 文件并且存放在 ASP.NET 应用程序的目录 Bin 中,那么你还需要指定相应的汇编集名称。如果你把 HTTP 模块的源代码文件保存在 ASP.NET 应用程序的目录 App_Code 中,那么你就不需要指定汇编集名称。

如果进行适当的改进并且用户拥有对文件 Web.config 的读取和写入权限,该代码也可以从某个 .aspx 页面中开始运行。通常,服务器管理员会对这些权限进行限制。


using System;

using System.Collections.Generic;

using System.Text;

using System.Configuration;

using System.Web.Configuration;



namespace Samples.Aspnet.Configure

{

    class ConfigureHttpModule

    {

        static void Main(string[] args)

        {

            try

            {

                // 设置 configPath 的值为你的目标网站路径。

                string configPath = "/Temp";



                // 获得配置对象。

                Configuration config =

                  WebConfigurationManager.OpenWebConfiguration(configPath);



                // 调用子程序 EnumerateHttpModules。

                EnumerateHttpModules(config);



                // 调用子程序 ConfigureHttpModules。

                ConfigureHttpModules(config);

            }

            catch (ArgumentException e)

            {

                Console.WriteLine(e.ToString());

            }

        }



        private static void ConfigureHttpModules(Configuration config)

        {

            Console.WriteLine();



            // 获得配置段 <httpModules> 。

            HttpModulesSection section = 

                (HttpModulesSection)config.GetSection("system.web/httpModules");



            // 创建一个新的模块动作对象。

            HttpModuleAction myHttpModuleAction = new HttpModuleAction(

                "RequestTimeIntervalModule",

                "Samples.Aspnet.HttpModuleExamples.RequestTimeIntervalModule");

            

            // 查看该模块是否已经配置。

            int indexOfModule = section.Modules.IndexOf(myHttpModuleAction);

            if (-1 != indexOfModule)

            {

                Console.WriteLine("模块 RequestTimeIntervalModule 已经在索引 {0} 中被配置",

                    indexOfModule);

                Console.WriteLine("是否删除现有的模块配置?(Yes/No)");

                string deleteModule = Console.ReadLine();

                if (("Y" == deleteModule) || ("y" == deleteModule))

                {

                    section.Modules.Remove("RequestTimeIntervalModule");

                    if (!section.SectionInformation.IsLocked)

                        config.Save();



                    Console.WriteLine("现有的模块配置 RequestTimeIntervalModule 已经被删除");

                    Console.WriteLine("重新运行该工具重新配置 RequestTimeIntervalModule 模块。");

                }

                else

                {

                    Console.WriteLine("配置未被更改");

                }

            }

            else

            {

                section.Modules.Add(myHttpModuleAction);



                if (!section.SectionInformation.IsLocked)

                {

                    config.Save();

                    Console.WriteLine("模块 RequestTimeIntervalModule 已经被配置。");

                }

                else

                {

                    Console.WriteLine("无法配置模块 RequestTimeIntervalModule。");

                }

            }



        }



        private static void EnumerateHttpModules(Configuration config)

        {

            Console.WriteLine();



            // 获得配置段 <httpModules>。

            HttpModulesSection section = 

                (HttpModulesSection)config.GetSection("system.web/httpModules");



            StringBuilder output = new StringBuilder();

            output.AppendFormat("索引 {0} 中的模块元素 <httpModules>:\r\n", 

                config.FilePath.ToString());



            for (int i = 0; i < section.Modules.Count; i++)

            {

                output.AppendFormat("  {0}, {1}\r\n", 

                    section.Modules[i].Name.ToString(), 

                    section.Modules[i].Type.ToString());

            }



            Console.WriteLine(output);



        }

    }

}

HTTP 模块实例的使用

使用代码实例时必须先完成下列准备步骤。

提示:你必须在局域网环境中运行该实例,这样你才可以使用 Windows 的验证机制对用户进行验证。默认时,只有管理员才拥有文件 Web.config 的读取和写入权限。

如何创建 HTTP 模块
  1. 把 HTTP 模块(HTTP 模块实例)的代码编译成类库 RequestTimeIntervalModule。这样会为汇编集产生一个 DLL 文件。

  2. 创建 Web 应用程序 Test。你可以在 IIS 中为该应用程序创建虚拟目录 Test。关于 IIS 虚拟目录的创建和配置的相关信息,请参考“ASP.NET 实践:在 IIS 中创建并配置虚拟目录”。

  3. 直接在 Web 应用程序(也被称作 Web 应用程序根目录)下创建子目录 Bin。

  4. 复制文件 RequestTimeIntervalModule.dll 到目录 Bin 中。

    提示:另外,你可以使用 ASP.NET 的动态编译特征对自定义 HTTP 模块代码进行测试,而不需要将其预编译成汇编集 DLL。ASP.NET 会对源代码进行动态编译,并把编译结果保存网站的目录 App_Code 中。因此,目录 App_Code 中的源文件中的类不需要预编译进汇编集中就可以被页面访问。目录 App_Code 是 ASP.NET 2.0 中的一个新特征。把自定义 HTTP 模块代码保存到目录 App_Code 中使得你在不需要对代码进行预编译的情况下而完成对模块的测试变得更加容易。关于如何使用这类实现的实例,请参考“ASP.NET 实践:创建自定义 HTTP 模块”。关于编译选项,请参考“ASP.NET 编译模型”。

HTTP 模块实例的配置

该代码实例中使用了类 HttpModuleSection 以及配置应用程序的对象类型。

如何配置 HTTP 模块
  1. 为配置 HTTP 模块(HTTP 模块配置的代码实例)而把代码编译成控制台应用程序。

  2. 请在命令行中调用你的控制台应用程序。如果没有 HTTP 模块 RequestTimeIntervalModule 的设定,将会自动被创建。如果 ASP.NET 应用程序中没有文件 Web.config,也会自动被创建,并且与新的设定一起被创建。该设定可能跟下例元素 httpModules 类似,该元素是文件 Web.config 中 system.web 的子元素。

    
    <httpModules>
    
      <add name="RequestTimeIntervalModule"  type="Samples.Aspnet.HttpModuleExamples.RequestTimeIntervalModule"  </add>
    
    </httpModules>
    
    

HTTP 模块实例的测试

HTTP 模块允许你对超出范围的响应进行检查并且进行更改。HTTP 模块 RequestTimeIntervalModule 使用属性 System.Web.HttpResponse.Output 在回应体中添加文本内容。

如何测试 HTTP 模块
  1. 在根目录中创建空白的 ASP.NET 页面 Defautl.aspx。

  2. 打开网页浏览器并在应用程序 Test 中发送对页面 Default.aspx 的请求。

    HTTP 模块 RequestTimeIntervalModule 在 ASP.NET 应用程序的任何一个被请求的页面中都会添加下列文本内容:

    
    当前用户:<用户名称>
    
    请求开始事件和请求结束事件之间的时间间隔:<时间间隔>
    
    你的友好 HttpModule:RequestTimeIntervalModule
    
    

你可能感兴趣的:(asp.net)