asp.net本质论——HttpModule

处理 HttpApplication 的事件
HttpApplication 提供了基于事件的扩展机制,允许程序员借助于处理管道中的事件进行处理过程扩展。由于 HttpApplication 对象是由 ASP.NET 基础架构来创建和维护的,那么,如何才能获取这个对象引用,以便于注册 HttpApplication 对象的事件处理,就是程序员首先要解决的问题。在 ASP.NET 中,提供了两种方式来解决这个问题:IHttpModule 方式和 global.asax 方式。这两种方式的核心都是 IHttpModule 接口。
通过 IHttpModule 创建 HttpApplication 的事件处理程序
在 ASP.NET中,定义在System.Web 命名空间下的 IHttpModule 接口专门用来定义 HttpApplication对象的事件处理。
实现 IHttpModule 接口的类称为 HttpModule。IHttpModule 接口的定义如下,其中仅仅包含两个成员:
public interface IHttpModule  {
      void Dispose()
      void Init( HttpApplication context )
  }
其中,Dispose 方法用于回收 Module 所使用的非托管资源,如果没有的话,直接返回即可。
最重要的是 Init 方法,可以看到,这个方法接收一个 HttpApplication 类型的参数,在 ASP.NET 中,每当创建一个 HttpApplication 对象实例,将遍历注册的 HttpModule 类型,通过反射,依次创建每个注册 HttpModule 类型的一个实例对象,并将这个 HttpApplication 实例通过 Init 方法传递给各个 HttpModule,这样 HttpModule 就可以在第一时间完成针对 HttpApplication 对象的事件注册了。
例如,希望写一个处理 PostAuthenticateRequest 事件的 HttpModule,那么,可以如下完成事件的注册:
public void Init(System.Web.HttpApplication application)  
{
      application.PostAuthenticateRequest 
       += new EventHandler(Application_PostAuthenticateRequest);  
}
注册 HttpModule
在 ASP.NET 中,实现 IHttpModule 接口只是实现 HttpModule 的第一步,在 ASP.NET 中所使用的 HttpModule 还必须在网站配置文件中进行注册才能真正生效,并在 ASP.NET 中使用。
在 .NET 中,网站的配置文件分成三个级别,首先,在 .NET 的系统文件夹中,有针对本服务器所有 .NET 程序的配置文件,配置文件所在的文件夹位于如下位置:
操作系统文件夹\Microsoft.NET\Framework\ASP.NET版本\Config
在这个文件夹中,有两个重要的配置文件:machine.config 和 web.config。machine.config 配置文件中保存有针对此服务器所有 .NET 程序的基本配置参数。web.config 配置文件中保存有针对此服务器所有 Web 应用程序的基本配置参数。在我们开发的网站项目中的 web.config 中所做的配置是专门针对这个网站应用程序的配置文件,在网站应用程序中起作用的配置参数来自这三个配置文件的整合。
在 ASP.NET 的网站配置文件 web.config 中,system.web 配置元素的子元素 httpModules 用来配置网站所使用的 HttpModule;httpModules的子元素 add 用来增加一个新的 HttpModule;clear 将清除前面注册的所有 HttpModule。
add 元素有两个必选的属性 name 和 type,简介如下:
name 表示这个 HttpModule 在程序中的名字,在网站应用程序中,可以通过这个名字来找到 HttpModule 对象的引用。HttpApplication 的 Modules 属性表示这个对象所关联的所有 HttpModule 对象,通过这个 name 作为索引器,可以找到对应的 HttpModule 对象。
type 表示 HttpModule 对象的类型名,ASP.NET 网站可以使用这个类型名,通过反射来动态创建 HttpModule 对象。类型的写法就是反射中要求的类型名称写法,如果这个类定义在网站中,那么,就是一个包含命名空间的类的全名,否则的话,在全名的后面,使用逗号 ( , ) 分隔,还需要跟上类型所在程序集的名称,这个程序集的名称不需要包含 .dll 扩展名。
例如,自定义的 HttpModule 类位于程序集 OnlineUserModule 中,类的全名为 com.aspnet.OnlineUserModule,将这个自定义的 HttpModule 注册到网站中,那么配置文件中的定义如下所示:
<httpModules>
    <add name="online" type="com.aspnet.OnlineUserModule,OnlineUserModule"/>
</httpModules>
对于 IIS 7.0来说,需要在配置文件的 system.webServer 配置节中注册 HttpModule。注意此时的配置元素名称变为了 modules。 在 IIS 7.0 中,可以为 MapRequestHandler,LogRequest 和 PostLogRequest 事件添加处理程序。只有在 IIS 7.0 集成模式下运行并且与 .NET Framework 3.0 或更高版本一起运行的应用程序,才可以支持这些事件。
<system.webServer>
   <modules>
     <add name="ModuleExample" type="Samples.ModuleExample"/>
   </modules>
</system.webServer>
托管代码模块也可以在 IIS 7.0 配置存储区(ApplicationHost.config 文件)的 modules 元素中注册。在 ApplicationHost.config 文件中注册的模块具有全局范围,因为它们为所有由 IIS 7.0 承载的 Web 应用程序而注册。同样,在 ApplicationHost.config 文件的 globalModules 元素中定义的本机代码模块也具有全局范围。如果 Web 应用程序不需要全局模块,则可以将其禁用。
不使用配置文件注册 HttpModule
在 ASP.NET 4.0 中,还可以不通过修改配置文件来完成 Moudle 的注册。从 .NET 3.5 开始,新提供的 PreApplicationStartMethodAttribute 特征可以应用在程序集上,使得自定义的网站初始化代码可以在 Web 应用程序的Application_Start初始化环节之前就执行。这个步骤甚至在动态编译和执行 Application_Start 之前。对于每个程序集,可以定义一次。特征的定义如下:
[AttributeUsageAttribute(AttributeTargets.Assembly,AllowMultiple = false)]
public sealed class PreApplicationStartMethodAttribute : Attribute  {
      public Type Type { get; }
      public string MethodName { get; }
      ......  
}
Type 用来指定定义了初始化方法的类型,MethodName 用来指定将要执行的初始化方法。
这样,可以不在配置文件中固定配置 HttpModule,而是定义一个方法,这个方法可以返回需要动态注册的 HttoModule,将这个方法以委托的形式登记在一个集合中。在网站启动之后,每当 HttpApplicationFactory 创建一个 HttpApplication 对象,完成正常注册的 HttpModule 创建及初始化之后,再来创建我们动态注册的这些 HttpModule。
对于 HttpApplication 来说,其 Init 方法将在网站正常注册的 HttpModule 创建及注册之后被调用,用来完成自定义的 HttpApplication 初始化。我们可以在这个时间点动态注册 HttpModule。在 ASP.NET 网站中,Global.asax 文件用来生成一个 HttpApplication 的派生类,这个类用来创建网站中使用的 HttpApplication 对象,我们可以重写这个派生类的 Init 方法,完成动态注册的 HttpModule 创建和注册工作。
<script runat="server">
      private List<IHttpModule> dynamicModules;
      public override void Init()
      {
          base.Init();
           this.dynamicModules = DynamicHttpModuleManager.GetModules();
          foreach (IHttpModule module in this.dynamicModules)
          {
              module.Init(this);
          }
      }
//这个在Global.asax文件
在网站初始化之前,将需要注册的 Module 类型记录在一个集合中。
public delegate IHttpModule CreateDynamicHttpModule(  );

public static class DynamicHttpModuleManager
{
      private static List<CreateDynamicHttpModule> _createModuleHandlerList = new List<CreateDynamicHttpModule>();

       public static void RegisterDynamicModule(CreateDynamicHttpModule handler )
      {
          _createModuleHandlerList.Add(handler);
      }

       public static List<IHttpModule> GetModules()
      {
          List<IHttpModule> list = new List<IHttpModule>();
          foreach (CreateDynamicHttpModule handler in _createModuleHandlerList)
          {
              IHttpModule module = handler();
              list.Add(module);
          }
          return list;
      }
}
在 Module 中增加一个用于注册的方法 Register,注意,必须是 public 和 static 。
namespace DiskFileUpload
{
      public class UploadModule : System.Web.IHttpModule
      {
          public static void Register()
          {
              DynamicHttpModuleManager.RegisterDynamicModule
                  (
                      ()=>new UploadModule()
                  );
          }
      }
}
最后,在项目的 AssemblyInfo.cs 文件中增加 PreApplicationStartMethod 特征完成动态注册。
[assembly: PreApplicationStartMethod(typeof(DiskFileUpload.UploadModule),"Register")]
常见的 HttpModule
在 ASP.NET 中,已经预定义了许多HttpModule,甚至已经在服务器的网站配置文件中进行了注册,在系统文件夹 C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config 中,web.config 文件中已经注册了 14 个 HttpModule。
<httpModules>
     <add name="OutputCache" type="System.Web.Caching.OutputCacheModule" />
     <add name="Session" type="System.Web.SessionState.SessionStateModule" />
     <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" />
     <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
     <add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule" />
     <add name="RoleManager" type="System.Web.Security.RoleManagerModule" />
     <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
     <add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" />
     <add name="AnonymousIdentification" type="System.Web.Security.AnonymousIdentificationModule" />
     <add name="Profile" type="System.Web.Profile.ProfileModule" />
     <add name="ErrorHandlerModule" type="System.Web.Mobile.ErrorHandlerModule, System.Web.Mobile, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
     <add name="ServiceModel" type="System.ServiceModel.Activation.HttpModule, System.ServiceModel.Activation,Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
     <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />
     <add name="ScriptModule-4.0" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</httpModules>
主要的HttpModule的解释如下:
OutputCacheMudole 完成ASP.NET的输出缓存管理工作。
OutputCacheMudole的配置参数通过system.web配置元素的caching子元素的 outputCache元素进行定义。当启用输出缓存之后,OutputCacheMudole 将注册 HttpApplication 的ResolveRequestCache 和 UpdateRequestCache 两个事件完成输出缓存的管理。
SessionStateModule 完成 Session 的管理工作。
这个 Module 的配置参数通过配置文件中的 system.web 配置元素的 sessionState 子元素进行配置。当启用 Session 状态管理之后,SessionStateModule 将注册 HttpApplication 的AcquireRequestState、ReleaseRequestState、EndRequest三个事件完成 Session 状态的管理工作。
ProfileModule 在 .NET 2.0 之后,提供个性化数据管理。
这是一个自定义的类似于 Session 的会话状态管理,但是,个性化数据的读取和保存可以由程序员完全控制,并且提供了强类型的数据访问方式。这个 Module 的配置参数在 system.web 的子元素 profile 中进行说明。当启用了个性化数据管理之后,Module 将注册 HttpApplicaiton 的 AcquireRequestState 和EndRequest 事件处理。
AnonymousIdentificationModule 提供匿名用户的标识。
是否启用匿名用户标识在配置文件的system.web配置元素的子元素 anonymousIdentification 中定义,还可以配置匿名标识的管理方式。由于在 AuthenticateRequest 事件中将验证用户,获取用户名,所以,这个 Module 注册了 PostAuthenticateRequest 的事件处理,当用户没有经过验证的时候,为用户分配一个唯一的匿名标识。
WindowsAuthenticationModule、FormsAuthenticationModule和PassportAuthenticationModule用来完成用户的验证工作。
它们通过配置文件中 system.web 的子元素 authentication 子元素定义,mode 属性用来指定网站当前使用的验证方式,也就是哪一个 Module 将被用来完成验证工作。在启用验证的情况下,FormsAuthenticationModule 和 PassportAuthenticationModule将注册 HttpApplication 的AuthenticateRequest 和 EndRequest 事件进行用户的验证处理。 WindowsAuthenticationModule 将注册 AuthenticateRequest 的事件处理。
RoleManagerModule、UrlAuthorizationModule、FileAuthorizationModule 用来完成用户的授权管理。
授权管理的配置参数来自 system.web 的 authorization 子元素。UrlAuthorizationModule 和 FileAuthorizationModule 注册了 HttpApplication 的 AuthorizeRequest 事件处理,用来检查 Url 和 文件的访问授权。RoleManagerModule 在 Url 和 文件访问授权检查通过之后,通过用户的标识和角色来完成用户的授权检查,RoleManagerModule 注册了 HttpApplication 的 PostAuthenticateRequest 和 EndRequest 事件处理。
HttpModule的事件
每个 HttpModule 也可以触发自定义的事件,但是,处理这些 HttpModule事件更加麻烦一些,因为这些 HttpModule 对象实例也不是我们自己创建的。
一般来说,可以通过 HttpApplication 的 Modules 属性获取特定的 HttpModule ,这个属性的定义如下:
public HttpModuleCollection Modules { get; }
可以使用定义 HttpModule 时候的 name 做为索引器来获取对应的 HttpModule。例如,获取前面定义的 HttpModule 对象的引用,可以如下进行。
application. Modules["online" ]
然后,就可以定义这个 HttpModule 的事件处理了。
不过,这样比较麻烦,更加简单的方式是在 Global.asax 中进行事件处理。
创建和注册自定义 HTTP 模块  http://msdn.microsoft.com/zh-cn/library/ms227673(v=vs.100).aspx
IHttpModule 接口   http://msdn.microsoft.com/zh-cn/library/system.web.ihttpmodule(v=vs.80).aspx


通过 为知笔记 发布


转载于:https://www.cnblogs.com/weapon/archive/2012/12/22/2828746.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/548172.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

细分shared_ptr智能指针在各个版本的使用情况

#include <memory> #include <iostream> class A { public: A(int value) :value_(value) { } private: int value_; }; int main() { //c17之前语法 std::shared_ptr<int> shared_good(new int[10],std::default_delete<int[]>(…

emplace_back和push_back区别

#include <vector> #include <iostream> using namespace std; class testDemo { public: testDemo(int num) :num(num) { std::cout << "调用构造函数" << endl; } testDemo(const testDemo& other) :num(other.…

RAC 之 RMAN 备份

RAC 之 RMAN 备份 这篇主要介绍的是RAC 环境下的RMAN 备份。 关于Oracle 备份与恢复的一些理论知识参考我的Blog&#xff1a; Oracle 备份 与 恢复 概述 http://blog.csdn.net/tianlesoftware/archive/2010/04/16/5490733.aspx 一&#xff0e; RAC 归档的设置 1.1 相关理论…

实时监控文件操作

#include <iostream> #include <windows.h> #include <thread> #include <vector> #define BUFFER_SIZE 2048 std::vector<char>g_buffers; // 监控函数 BOOL MonitorFile(std::wstring&path) { PTCHAR pszDirectory (PTCHAR)(path.c_str(…

Spring的基本使用

Java类一般的设计方法 —— 一个类做一方面工作&#xff0c;一个方法完成一件事情。 什么是Spring&#xff1f; Spring框架技术的构成&#xff08;7大核心功能&#xff09;&#xff1a;Spring Core&#xff08;内核&#xff09;、Spring AOP&#xff08;面向切面编程&#xff0…

Storyboard初体验

2019独角兽企业重金招聘Python工程师标准>>> Storyboard是iOS5的新特性。使用Storyboard可以更方便的管理应用的界面&#xff0c;同时为视图间的跳转提供了清晰的脉络。 任何时候你都可以在你的项目中添加Storyboard&#xff0c;不管你创建项目的时候有没有勾选“U…

网络地址 子网掩码 广播地址计算

已知一个ip地址是192.168.1.1&#xff0c;子网掩码是255.255.255.0&#xff0c;那么它的网络地址是多少&#xff1f; 192.168.1.0 已知某主机的ip地址是192.168.100.200&#xff0c;子网掩码为255.255.255.192&#xff0c;其网络内可用的ip地址个数为多少 62 1111 1111 1111 …

linux服务之DHCP

转自&#xff1a;http://best0.blog.51cto.com/444987/104151用Linux做DHCP服务器&#xff0c;原理跟在windows环境下、路由器上做DHCP相同&#xff0c;所以不在这里介绍了。我们直接开始配置dhcp服务器。这次介绍用Linux配置DHCP服务器&#xff0c;我以实验理论的方式介绍&…

Oracle RAC更改VIP IP地址_2节点的实验

本文转载&#xff1a;http://space.itpub.net/9664900/viewspace-676800 1、主机名规划&#xff1a; --更改前&#xff1a; #Public Network - (eth0) 192.168.10.11 rac1 192.168.10.12 rac2 #Private Interconnect - (eth1) 10.10.10.11 rac1priv 10.10.10.12 ra…

模板全特化和偏特化用法

#include <iostream> template <typename T, typename U> class TC { public: TC() { std::cout << "泛化版本构造函数" << std::endl; } void funtest() { std::cout << "泛化版本成员函数…

IIS Express 使用详细说明

最近在使用XP的IIS发布Asp.Net MVC3的项目&#xff0c;但是发现一个很头疼的一个问题&#xff0c;在IIS指定虚拟目录来发布网站发布不了&#xff0c;以前发布Webfrom项目则不会有这样的问题&#xff0c;应该是跟路由路径有关系&#xff0c;导致每次都是从网站根节点算起&#x…

qt项目转vs项目

先执行一下命令&#xff1a; call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat" SET "PATHD:\soft_install\qtcreator\5.12.10\msvc2017_64\bin;%PATH%" pause 执行完以上命令之后&#xff0c;再…

离奇的xenapp客户端无法加载应用故障解决过程 ...

新建的xenapp 6.5 for 2008 简体中文版&#xff0c;弄好之后从客户端去访问&#xff0c;结果报错&#xff08;当时忘了截图下来&#xff09;&#xff0c;大致意思就是说服务器无法处理我的请求。确认安装过程正确&#xff0c;程序发布正常。排查过程发现通过RDP的远程桌面可以加…

时间管理,从洗碗开始

笔者的前一篇博文《你是怎么利用时间的&#xff1f;》&#xff0c;自发表后得到了一些读者的关注和好评。更有甚者&#xff0c;博友shyy8712872还进一步发表了博文《老生常谈的时间你真的管理好了吗&#xff1f;》&#xff0c;并在其中引用了我的原话。这都令笔者深感欣慰、荣幸…

ADDS学习(下)

任务三&#xff1a;完成活动目录备份和恢复 1) 验证第一部分用户和OU是否存在 2) 备份活动目录 3) 删除一个OU 4) 恢复 5) 验证恢复是否成功 如下图&#xff0c;qingfeng.com域中有OU和用户&#xff0c; 要备份活动目录&#xff0c;使用微软的windows server backup工具&#x…

linux下boost库链接动态库失败

echo "boost库lib安装路径" >>/etc/ld.so.conf 加入动态库的地方 执行动态库命令 sudo ldconfig

一些Web Service的经验

使用Web服务也有半年多了&#xff0c;虽然时间不长&#xff0c;但还是遇到了不少难题&#xff0c;在这里把我的一些经验拿出来给大家共同分享。 刚开始做Web服务的时候还觉得很轻松&#xff0c;感觉就跟写一般的组件没什么区别&#xff0c;而使用时跟引用普通的程序集一样的简单…

递归1

此次做项目使用JDBC&#xff0c;遇到了一个树形结构&#xff0c;采用递归查找父类&#xff0c;有了一个初步的认识。 public Channel findParent(int id){ if (id0) { return null; }else { int parent 1; Channel cnew Chan…

ssh 脚本 空格字符转换

yum install -y doc2unix && doc2unix *.sh

⑨④-如果不发展就可能面临生存窘境

⑨④-如果不发展就可能面临生存窘境 老男孩语录⑨④-如果不发展就可能面临生存窘境 现实很残酷&#xff0c;如果你不去思考如何发展自己&#xff0c;就可能面临生存的窘境&#xff01; 上面这句话不光适合某一个个体人类&#xff0c;小到一个家庭&#xff0c;一个公司&#xff…