python做网站的优势,环球设计官网网站,专门做投票的网站有哪些,网站设计制作价钱引言
Http 请求处理流程 和 Http Handler 介绍 这两篇文章里#xff0c;我们首先了解了Http请求在服务器端的处理流程#xff0c;随后我们知道Http请求最终会由实现了IHttpHandler接口的类进行处理(应该记得Page类实现了IHttpHandler)。从 Http 请求处理流程 一文的最后的一…引言
Http 请求处理流程 和 Http Handler 介绍 这两篇文章里我们首先了解了Http请求在服务器端的处理流程随后我们知道Http请求最终会由实现了IHttpHandler接口的类进行处理(应该记得Page类实现了IHttpHandler)。从 Http 请求处理流程 一文的最后的一幅图中可以看到在Http请求由IHttpHandler处理之前它需要通过一系列的Http Module在请求处理之后它需要再次通过一系列的Http Module那么这些Http Module是如何组成的用来做什么呢本文将对Http Module作以介绍。
Http Module概述
暂时先不考虑我们自己实现Http Module的情况。在.Net中Http Module 是实现了IHttpModule接口的程序集。IHttpModule 接口本身并没有什么好大写特写的由它的名字可以看出它不过是一个普普通通的接口而已。实际上我们关心的是实现了这些接口的类如果我们也编写代码实现了这个接口那么有什么用途。一般来说我们可以将Asp.Net中的事件分成三个级别最顶层是 应用程序级事件、其次是页面级事件、最下面是控件级事件事件的触发分别与 应用程序周期、页面周期、控件周期紧密相关。而 Http Module 的作用是与应用程序事件 密切相关的。
我们通过Http Module在Http请求管道(Pipeline)中注册期望对应用程序事件做出反应的方法在相应的事件触发的时候(比如说BeginRequest事件它在应用程序收到一个Http请求并即将对其进行处理时触发)便会调用Http Module注册了的方法实际的工作在这些方法中执行。.Net 本身已经有很多的Http Module其中包括 表单验证Module(FormsAuthenticationModule) Session 状态Module(SessionStateModule)输出缓存Module (OutputCacheModule)等。
注册 Http Module
在注册我们自己编写的 Http Module 之前先来看看Asp.Net中已经有的HttpModule。与 Http Handler类似我们需要打开机器上C:\WINDOWS\Microsoft.NET\Framework\ v2.0.50727\CONFIG 目录下的 web.config 文件。找到 httpModules/ 结点应该可以看到下面的内容
httpModules add nameOutputCache typeSystem.Web.Caching.OutputCacheModule / add nameSession typeSystem.Web.SessionState.SessionStateModule / add nameWindowsAuthentication typeSystem.Web.Security.WindowsAuthenticationModule / add nameFormsAuthentication typeSystem.Web.Security.FormsAuthenticationModule / add namePassportAuthentication typeSystem.Web.Security.PassportAuthenticationModule / add nameRoleManager typeSystem.Web.Security.RoleManagerModule / add nameUrlAuthorization typeSystem.Web.Security.UrlAuthorizationModule / ... 略 /httpModules
我们先从结点上看type属性与上一节所说的http handler结点的type属性类似都代表了相应的程序集。但是与http handler 不同module只提供了一个name属性没有诸如 path这样指定某一特定(或者用通配符 * 代表某一种类)文件的处理程序。这是与Module的特点相关的我们知道 module 是响应应用程序周期中触发的事件对于所有提交到aspnet_isapi.dll的请求都一样即便请求只是像类似http://www.tracefact.net/images/logo.gif 这样获取一张图片而已(对ISAPI进行过设置以后默认aspnet_isapi.dll不接手图片文件)。
与Http handler类似在这册我们自己的http module 时假设类名为ModuleDemo位于myNameSpace命名空间下程序集名称为myDll我们只需将myDll.dll拷贝到Bin目录下并在站点的 web.config 文件 system.web 结点下创建 httpModules 结点
system.web httpModules add nameCustomModuleName typemyNameSpace.ModuleDemo, myDll/ /httpModules /system.web
type属性由分号“,”分为两部分前面是命名空间及类名也就是类型名后面是程序集名。如果我们将代码创建在App_Code目录中则不需要再指定程序集名。
name属性由我们自己命名不一定与类名相同此处我将它命名为“CustomModuleName”。我们可以通过应用程序(HttpApplication)的Modules属性获取HttpModuleCollection集合然后通过name属性进一步获取HttpModule对象。
通过name属性我们还可以在global.asax中文件中编写自定义HttpModule暴露出的事件的处理程序它采用的格式是void ModuleName_EventName(object sender, EventArgs e)。我们将在后面做更详细介绍。
Asp.Net 内置的 Http Modules
下面这张表格列出了C:\WINDOWS\Microsoft.NET\Framework\ v2.0.50727\CONFIG下的Web.Config中的 Asp.Net 内置的Http Modules 及其主要作用。
名称类型功能OutputCacheSystem.Web.Caching.OutputCacheModule页面级输出缓存SessionSystem.Web.SessionState.SessionStateModuleSession状态管理WindowsAuthenticationSystem.Web.Security.WindowsAuthenticationModule用集成Windows身份验证进行客户端验证FormsAuthenticationSystem.Web.Security.FormsAuthenticationModule用基于Cookie的窗体身份验证进行客户端身份验证PassportAuthenticationSystem.Web.Security.PassportAuthenticationModule用MS护照进行客户身份验证RoleManagerSystem.Web.Security.RoleManagerModule管理当前用户角色UrlAuthorizationSystem.Web.Security.UrlAuthorizationModule判断用户是否被授权访问某一URLFileAuthorizationSystem.Web.Security.FileAuthorizationModule判断用户是否被授权访问某一资源AnonymousIdentificationSystem.Web.Security.AnonymousIdentificationModule管理Asp.Net应用程序中的匿名访问ProfileSystem.Web.Profile.ProfileModule管理用户档案文件的创立 及相关事件ErrorHandlerModuleSystem.Web.Mobile.ErrorHandlerModule捕捉异常格式化错误提示字符传递给客户端程序
我们将在后面用编程的方式来查看它。
IHttpModule接口
看了这么多理论知识本节将开始动手写点程序实现自己的Http Module。我们首先需要看下IHttpModule 接口它包括下面两个方法
public void Init(HttpApplication context); public void Dispose();
Init()这个方法接受一个HttpApplication对象HttpApplication代表了当前的应用程序我们需要在这个方法内注册 HttpApplication对象暴露给客户端的事件。可见这个方法仅仅是用来对事件进行注册而实际的事件处理程序需要我们另外写方法。
整个过程很好理解
当站点第一个资源被访问的时候Asp.Net会创建HttpApplication类的实例它代表着站点应用程序同时会创建所有在Web.Config中注册过的Module实例。在创建Module实例的时候会调用Module的Init()方法。在Init()方法内对想要作出响应的HttpApplication暴露出的事件进行注册。(仅仅进行方法的简单注册实际的方法需要另写)。HttpApplication在其应用程序周期中触发各类事件。触发事件的时候调用Module在其Init()方法中注册过的方法。
NOTE如果你不了解事件注册等相关内容请参阅 C#中的委托与事件 一文。
Dispose()它可以在进行垃圾回收之前进行一些清理工作。
综上所述实现一个 IHttpModule 的模板一般是这样的
public class ModuleDemo:IHttpModule { public void Init(HttpApplication context) { // 注册HttpApplication应用程序 BeginRequest 事件 // 也可以是其他任何HttpApplication暴露出的事件 context.BeginRequest new EventHandler(context_BeginRequest); } void context_BeginRequest(object sender, EventArgs e) { HttpApplication application (HttpApplication)sender; HttpContext context application.Context; // 做些实际的工作HttpContext对象都获得了剩下的基本可以自由发挥了 } public void Dispose() { } }
通过Http Module向Http请求输出流中写入文字
本例中我们仅用BeginRequest事件和 EndRequest 事件对 Http Module 的使用作以说明。我们通过这个范例了解 Http Module 基本的使用方法。
首先请创建一个新的站点在App_Code目录中添加类文件 ModuleDemo.cs
public class ModuleDemo:IHttpModule { // Init方法仅用于给期望的事件注册方法 public void Init(HttpApplication context) { context.BeginRequest new EventHandler(context_BeginRequest); context.EndRequest new EventHandler(context_EndRequest); } // 处理BeginRequest 事件的实际代码 void context_BeginRequest(object sender, EventArgs e) { HttpApplication application (HttpApplication)sender; HttpContext context application.Context; context.Response.Write(h1 stylecolor:#00f来自HttpModule 的处理请求到达/h1hr); } // 处理EndRequest 事件的实际代码 void context_EndRequest(object sender, EventArgs e) { HttpApplication application (HttpApplication)sender; HttpContext context application.Context; context.Response.Write(hrh1 stylecolor:#f00来自HttpModule的处理请求结束/h1); } public void Dispose() { } }
上面的代码很简单它注册了 HttpApplication实例的 BeginRequest 事件 和 EndRequest事件事件处理方法的作用仅仅是在http请求开始和结束的时候给http请求的输入流中分别写入不同的内容。
接下来在 Web.config 的 System.web 结点中写入以下内容
system.web httpModules add nameMyModule typeModuleDemo / /httpModules /system.web
然后打开建立站点时自动创建的 Default.aspx文件在里面打几个字为了做区分我输入的是位于.aspx页面上的文字。然后我们在浏览器中打开它应该会看到像这样 然后我们再新建一个 Default2.aspx在浏览器中浏览可以看到两个页面的效果相同。这说明对于不同的两个文件http Module都起了作用可见它确实是位于应用程序级而非页面级。
现在我们再打开站点中的一张图片文件发现显示出的是一个红叉叉为什呢因为Http Module 针对是http 请求而不是某个或某一类文件所以当请求一张图片的时候我们编写的http Module依然会起作用将文字插入到二进制图片中破坏了文件格式自然只能显示红叉叉了。
NOTE如果你发现你的图片显示正常请不要惊讶事情是这样的回想一下第一节我们讨论到的对于图片文件由IIS直接处理并不会交由aspnet_isapi.dll所以Module无法捕获对于图片类型文件的请求。解决方法就是在IIS中进行设置一下。 这里需要提请注意的是如果你使用Vs2005自带的Local Server那么你无需对IIS进行设置所有的不论图片还是任何文件类型都会交由aspnet_isapi.dll处理。
遍历Http Module集合
现在我们通过遍历 HttpModuleCollection 集合来查看注册给应用程序的所有 Http Module 的名称。
新建一个文件 RegisteredModules.aspx在代码后置文件中添加如下方法
private string ShowModules() { HttpApplication app Context.ApplicationInstance; //获取当前上下文的HttpApplication环境 HttpModuleCollection moduleCollection app.Modules; //获取所有Module集合 // 获取所有的 Module 名称 string[] moduleNames moduleCollection.AllKeys; System.Text.StringBuilder results new System.Text.StringBuilder(); //遍历结果集 foreach (string name in moduleNames) { // 获得Module名称 results.Append(b stylecolor:#800800名称 name /bbr /); // 获得Module类型 results.Append(类型 moduleCollection[name].ToString() br /); } return results.ToString(); }
然后在Page_Load方法中输出一下
protected void Page_Load(object sender, EventArgs e) { Response.Write(ShowModules()); }
我们应该可以看到下面这样的画面 与之前列出的那张表格比较一下可以看出是几乎完全一致的(多了一个DefaultAuthentication)。另外注意上图的倒数第四行那不是我们自己定义的Module么name为MyModule类型为ModuleDemo。
Global.asax文件与 Http Module
早在asp时代大家就知道这个文件了。它主要用于放置对于 应用程序事件或者 Session事件的响应程序。大家熟悉的有Application_Start、Application_End、Session_Start、Session_End 等。
在asp.net中Glabal不仅可以注册应用程序和Session事件还可以注册Http Module暴露出的事件不仅可以注册系统Module的事件也可以注册我们自己义的Module暴露出的事件。在具体介绍之前这里需要首先注意两点
在每处理一个Http请求时应用程序事件都会触发一遍但是Application_Start和 Application_End 例外它仅在第一个资源文件被访问时被触发。Http Module无法注册和响应Session事件对于Session_Start 和 Session_End只能通过Glabal.asax来处理。
好了我们现在修改之前 ModuleDemo 范例程序给它像下面这样给它添加一个事件(为了使程序简洁一些我做了简化)
public class ModuleDemo : IHttpModule { // 声明一个事件 public event EventHandler ExposedEvent; // Init方法仅用于给期望的事件注册方法 public void Init(HttpApplication context) { context.BeginRequest new EventHandler(context_BeginRequest); } // 处理BeginRequest 事件的实际代码 void context_BeginRequest(object sender, EventArgs e) { HttpApplication application (HttpApplication)sender; HttpContext context application.Context; context.Response.Write(h3 stylecolor:#00f来自HttpModule的处理请求到达/h3hr); OnExposedEvent(new EventArgs()); // 调用方法 } protected override void OnExposedEvent(EventArgs e) { if (ExposedEvent ! null) // 如果Global中有注册 ExposedEvent(this, e); // 调用注册了的方法 } public void Dispose() { } }
接下来我们在站点中创建一个 Global.asax 文件在里面添加如下代码注意到格式是void 模块名_事件名(object sender, EventArgs e)。
void MyModule_ExposedEvent(object sender, EventArgs e) { Response.Write(h3 stylecolor:#800800来自 Global.asax 的文字/h2); }
现在我们打开之前的页面应该可以见到这样可见我们成功的将 Glabal.asax文件与我们自己定义的Http Module所暴露出的事件 ExposedEvent 联系到了一起 总结
本文简单地介绍了什么是Http Module。我们首先了解了Http Module的作用然后查看了Asp.Net 内置的Module接着我们介绍了IHttpModule接口并通过了一个简单的范例实现了此接口最后我们讨论了 Http Module与 Global.asax 文件的联系。
本文仅仅是对IHttpModule作以简单介绍对其更多的实际应用会在后续文章中补充。
希望这篇文章能给你带来帮助
本文的源代码下载http://www.tracefact.net/sourcecode/Introduction-to-HttpModule.rar