`
winzenghua
  • 浏览: 1370727 次
  • 性别: Icon_minigender_2
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

HttpModule与HttpHandler详解(转载)

阅读更多

ASP.NET对请求处理的过程:
当请求一个*.aspx文件的时候,这个请求会被inetinfo.exe进程截获,它判断文件的后缀(aspx)之后,将这个请求转交给 ASPNET_ISAPI.dll,ASPNET_ISAPI.dll会通过http管道(Http PipeLine)将请求发送给ASPNET_WP.exe进程,在ASPNET_WP.exe进程中通过HttpRuntime来处理这个请求,处理完 毕将结果返回客户端。
inetinfo.exe进程:是www服务的进程,IIS服务和ASPNET_ISAPI.DLL都寄存在此进程中。
ASPNET_ISAPI.DLL:是处理.aspx文件的win32组件。其实IIS服务器是只能识别.html文件的,当IIS服务器发现被请求的文件是.aspx文件时,IIS服务器将其交给aspnet_isapi.dll来处理。
aspnet_wp.exe进程:ASP.NET框架进程,提供.net运行的托管环境,.net的CLR(公共语言运行时)就是寄存在此进程中。

ASP.NET Framework处理一个Http Request的流程:
HttpRequest-->inetinfo.exe-->ASPNET_ISAPI.dll-->ASPNET_WP.exe-->HttpRuntime-->HttpApplication Factory-->HttpApplication-->HttpModule-->HttpHandler Factory-->HttpHandler-->HttpHandler.ProcessRequest()

ASP.NET请求处理过程是基于管道模型的,这个管道模型是由多个HttpModule和HttpHandler组成,ASP.NET 把http请求依次传递给管道中各个HttpModule,最终被HttpHandler处理,处理完成后,再次经过管道中的HTTP模块,把结果返回给 客户端。我们可以在每个HttpModule中都可以干预请求的处理过程。


注意:在http请求的处理过程中,只能调用一个HttpHandler,但可以调用多个HttpModule。
当请求到达HttpModule的时候,系统还没有对这个请求真正处理,但是我们可以在这个请求传递到处理中心(HttpHandler)之前附加一些其 它信息,或者截获的这个请求并作一些额外的工作,也或者终止请求等。在HttpHandler处理完请求之后,我们可以再在相应的HttpModule中 把请求处理的结果进行再次加工返回客户端。

HttpModule
HTTP模块是实现了System.Web.IhttpModule接口的类。
IHttpModule接口的声明:
public interface IHttpModule
{
void Init (HttpApplication context);
void Dispose ();
}
Init 方法:系统初始化的时候自动调用,这个方法允许HTTP模块向HttpApplication 对象中的事件注册自己的事件处理程序。
Dispose方法: 这个方法给予HTTP模块在对象被垃圾收集之前执行清理的机会。此方法一般无需编写代码。

HTTP模块可以向System.Web.HttpApplication对象注册下面一系列事件:
AcquireRequestState 当ASP.NET运行时准备好接收当前HTTP请求的对话状态的时候引发这个事件。
AuthenticateRequest 当ASP.NET 运行时准备验证用户身份的时候引发这个事件。
AuthorizeRequest 当ASP.NET运行时准备授权用户访问资源的时候引发这个事件。
BeginRequest 当ASP.NET运行时接收到新的HTTP请求的时候引发这个事件。
Disposed 当ASP.NET完成HTTP请求的处理过程时引发这个事件。
EndRequest 把响应内容发送到客户端之前引发这个事件。
Error 在处理HTTP请求的过程中出现未处理异常的时候引发这个事件。
PostRequestHandlerExecute 在HTTP处理程序结束执行的时候引发这个事件。
PreRequestHandlerExecute 在ASP.NET开始执行HTTP请求的处理程序之前引发这个事件。在这个事件之后,ASP.NET 把该请求转发给适当的HTTP处理程序。
PreSendRequestContent 在ASP.NET把响应内容发送到客户端之前引发这个事件。这个事件允许我们在内容到达客户端之前改变响应内容。我们可以使用这个事件给页面输出添加用于所有页面的内容。例如通用菜单、头信息或脚信息。
PreSendRequestHeaders 在ASP.NET把HTTP响应头信息发送给客户端之前引发这个事件。在头信息到达客户端之前,这个事件允许我们改变它的内容。我们可以使用这个事件在头信息中添加cookie和自定义数据。
ReleaseRequestState 当ASP.NET结束所搜有的请求处理程序执行的时候引发这个事件。
ResolveRequestCache 我们引发这个事件来决定是否可以使用从输出缓冲返回的内容来结束请求。这依赖于Web应用程序的输出缓冲时怎样设置的。
UpdateRequestCache 当ASP.NET完成了当前的HTTP请求的处理,并且输出内容已经准备好添加给输出缓冲的时候,引发这个事件。这依赖于Web应用程序的输出缓冲是如何设置的。

上面这么多的事件,我们看起来可能会有些眼晕,但没关系,下面一步一步地看。
HttpModule生命周期示意图

下面是事件的触发顺序:

BeginRequest和PreRequestHandlerExecute之间的事件是在服务器执行HttpHandler处理之前触发。
PostRequestHandlerExecute和PreSendRequestContent之间的事件是在服务器执行Handler处理之后触发。

下面我们看一下如何使用HttpModule来实现我们日常的应用:
HttpModule通过在某些事件中注册,把自己插入ASP.NET请求处理管道。当这些事件发生的时候,ASP.NET调用对相应的HTTP模块,这样该模块就能处理请求了。
1、向每个页面动态添加一些备注或说明性的文字:
有的网站每一个页面都会弹出一个广告或在每个页面都以注释形式(<!-- -->)加入网站的版权信息。如果在每个页面教编写这样的JS代码的话,对于大一点的网站,这种JS代码的编写与维护可是一个很繁琐枯燥的工作。
有了HttpModule我们就可以很简单地解决这个问题了。HttpModule是客户端发出请求到客户端接收到服务器响应之间的一段必经之路。我们完 全可以在服务器处理完请求之后,并在向客户端发送响应文本之前这段时机,把这段注释文字添加到页面文本之后。这样,每一个页面请求都会被附加上这段注释文 字。
这段代码究竟该在哪个事件里实现呢? PostRequestHandlerExecute和PreSendRequestContent之间的任何一个事件都可以,但我比较喜欢在EndRequest事件里编写代码。
第一步:创建一个类库ClassLibrary831。
第二步:编写一个类实现IHttpModule接口
class TestModule:IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
}
}
第三步:在Init事件中注册EndRequest事件,并实现事件处理方法
class TestModule:IHttpModule
{
public void Dispose(){}
public void Init(HttpApplication context)
{
context.EndRequest += new EventHandler(context_EndRequest);
}
void context_EndRequest(object sender, EventArgs e)
{
HttpApplication ha = (HttpApplication)sender;
ha.Response.Write("<!--这是每个页面都会动态生成的文字。--grayworm-->");
}
}
第四步:在Web.Conofig中注册一下这个HttpModule模块
<httpModules>
<add name="TestModule" type="ClassLibrary831.TestModule,ClassLibrary831"></add>
</httpModules>
name:模块名称,一般是类名
type:有两部分组成,前半部分是命名空间和类名组成的全名,后半部分是程序集名称,如果类是直接放在App_Code文件夹中,那程序名称是App_Code。
这样在Web站点是添加该类库的引用后,运行每个页面,会发现其源文件中都会加入“<!--这是每个页面都会动态生成的文字。--grayworm-->”这句话。同样的方法你也可以在其中加入JS代码。
2、身份检查
大家在作登录时,登录成功后,一般要把用户名放在Session中保存,在其它每一个页面的Page_Load事件中都检查Session中是否存在用户名,如果不存在就说明用户未登录,就不让其访问其中的内容。
在比较大的程序中,这种做法实在是太笨拙,因为你几乎要在每一个页面中都加入检测Session的代码,导致难以开发和维护。下面我们看看如何使用HttpModule来减少我们的工作量
由于在这里我们要用到Session中的内容,我们只能在AcquireRequestState和PreRequestHandlerExecute事 件中编写代码,因为在HttpModule中只有这两事件中可以访问Session。这里我们选择PreRequestHandlerExecute事件 编写代码。
第一步:创建一个类库ClassLibrary831。
第二步:编写一个类实现IHttpModule接口
class TestModule:IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
}
}
第三步:在Init事件中注册PreRequestHandlerExecute事件,并实现事件处理方法
class AuthenticModule:IHttpModule
{
public void Dispose(){}
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
}
void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
HttpApplication ha = (HttpApplication)sender;
string path = ha.Context.Request.Url.ToString();
int n = path.ToLower().IndexOf("Login.aspx");
if (n == -1) //是否是登录页面,不是登录页面的话则进入{}
{
if (ha.Context.Session["user"] == null) //是否Session中有用户名,若是空的话,转向登录页。
{
ha.Context.Response.Redirect("Login.aspx?source=" + path);
}
}
}
}
第四步:在Login.aspx页面的“登录”按钮中加入下面代码
protected void Button1_Click(object sender, EventArgs e)
{
if(true) //判断用户名密码是否正确
{
if (Request.QueryString["source"] != null)
{
string s = Request.QueryString["source"].ToLower().ToString(); //取出从哪个页面转来的
Session["user"] = txtUID.Text;
Response.Redirect(s); //转到用户想去的页面
}
else
{
Response.Redirect("main.aspx"); //默认转向main.aspx
}
}
}
第五步:在Web.Conofig中注册一下这个HttpModule模块
<httpModules>
<add name="TestModule" type="ClassLibrary831.TestModule,ClassLibrary831"></add>
</httpModules>
3、多模块的操作
如果定义了多个HttpModule,在web.config文件中引入自定义HttpModule的顺序就决定了多个自定义HttpModule在处理一个HTTP请求的接管顺序。

HttpHandler
HttpHandler是HTTP请求的处理中心,真正地对客户端请求的服务器页面做出编译和执行,并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。
HttpHandler与HttpModule不同,一旦定义了自己的HttpHandler类,那么它对系统的HttpHandler的关系将是“覆盖”关系。
IHttpHandler接口声明
public interface IHttpHandler
{
bool IsReusable { get; }
public void ProcessRequest(HttpContext context); //请求处理函数
}

示例:把硬盘上的图片以流的方式写在页面上
class TestHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
FileStream fs = new FileStream(context.Server.MapPath("worm.jpg"), FileMode.Open);
byte[] b = new byte[fs.Length];
fs.Read(b, 0, (int)fs.Length);
fs.Close();
context.Response.OutputStream.Write(b, 0, b.Length);
}
public bool IsReusable
{
get
{
return true;
}
}
}
Web.Config配置文件
<httpHandlers>
<add verb="*" path="*" type="ClassLibrary831.TestHandler,ClassLibrary831"></add>
</httpHandlers>
Verb属性:指定了处理程序支持的HTTP动作。*-支持所有的HTTP动作;“GET”-支持Get操作;“POST”-支持Post操作;“GET, POST”-支持两种操作。
Path属性:指定了需要调用处理程序的路径和文件名(可以包含通配符)。“*”、“*.aspx”、“showImage.aspx”、“test1.aspx,test2.aspx”
Type属性:用名字空间、类名称和程序集名称的组合形式指定处理程序或处理程序工厂的实际类型。ASP.NET运行时首先搜索bin目录中的DLL,接着在GAC中搜索。
这样程序运行的效果是该网站的任何一个页面都会显示worm.jpg图片。如何只让一个页面(default21.aspx)执行HttpHandler 中的ProcessRequest方法呢?最简单的办法是在Web.Config文件中把path配置信息设为default21.aspx。
根据这个例子大家可以考虑一下如何编写“验证码”了。

IHttpHandler工厂
IHttpHandlerFactory的作用是对IHttpHandler进行管理。工厂的作用请见http://hi.baidu.com/grayworm/blog/item/4a832160f8c9de46eaf8f8c1.html"
IHttpHandlerFactory接口的声明:
public interface IHttpHandlerFactory
{
IHttpHandler GetHandler (HttpContext context,string requestType,string url,string pathTranslated);
void ReleaseHandler (IHttpHandler handler);
}
GetHandler返回实现IHttpHandler接口的类的实例,ReleaseHandler使工厂可以重用现有的处理程序实例。
示例:两个用IHttpHandlerFactory来实现对不同HttpHandler的调用。
有两个HttpHandler:将图片显示在页面上的HttpHandler和生成验证码的Handler
//将图片显示在页面上的Handler
class TestHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
FileStream fs = new FileStream(context.Server.MapPath("worm.jpg"), FileMode.Open);
byte[] b = new byte[fs.Length];
fs.Read(b, 0, (int)fs.Length);
fs.Close();
context.Response.OutputStream.Write(b, 0, b.Length);
}
public bool IsReusable
{
get
{
return true;
}
}
}
//生成验证码的Handler
class CodeHandler:IHttpHandler
{
public bool IsReusable
{
get
{
return true;
}
}
public void ProcessRequest(HttpContext context)
{
Image b = new Bitmap(50,20);
Graphics g = Graphics.FromImage(b);
SolidBrush sb = new SolidBrush(Color.White);
Font f = new Font("宋体", 12);
string str = "";
Random r = new Random();
for (int i = 0; i < 4; i++)
{
str += r.Next(10);
}
g.DrawString(str,f,sb,0,0);
b.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
IHttpHandler工厂
class TestHandlerFactory : IHttpHandlerFactory
{
public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{

string fname = url.Substring(url.IndexOf('/') + 1);
while (fname.IndexOf('/') != -1)
fname = fname.Substring(fname.IndexOf('/') + 1);
string cname = fname.Substring(0, fname.IndexOf('.'));
string className ="";

className = "ClassLibrary831.CodeHandler";
object h = null;
try
{
//h = new TestHandler();
h = Activator.CreateInstance(Type.GetType(className));
}
catch (Exception e)
{
throw new HttpException("工厂不能为类型" + cname + "创建实例。", e);
}
return (IHttpHandler)h;
}
public void ReleaseHandler(IHttpHandler handler)
{
}
}(车延禄)
配置文件
<httpHandlers>
<add verb="*" path="default21.aspx,default22.aspx" type="ClassLibrary831.TestHandlerFactory,ClassLibrary831"></add>
</httpHandlers>

这样TestHandlerFactory就会根据请求的不同页面执行不同的HttpHandler处理程序了。

HttpHandler使用会话
如果要在处理程序中使用Session,那必须把该HttpHandler实现IRequiresSessionState接口,,IRequiresSessionState接口是个空接口,它没有抽象方法,只是一个标记。此处就不作例子验证了。

转载自:http://hi.baidu.com/zeratul_bb/blog/item/54db48d9bde028e138012f74.html

分享到:
评论

相关推荐

    httpmodule和httphandler

    ### httpmodule和httphandler详解 #### 一、概述 在ASP.NET开发中,`HttpModule`和`HttpHandler`是两个重要的概念,它们都属于HTTP运行时的一部分,用于处理HTTP请求的不同方面。掌握这两者之间的区别以及如何使用...

    ASP.NET架构详解HttpHandler和HttpModule高清PDF文字版

    在这个主题中,我们将深入探讨ASP.NET架构中的两个关键组件:HttpHandler和HttpModule。 **HttpHandler**是ASP.NET处理HTTP请求的核心组件。每个HTTP请求都会被路由到一个特定的HttpHandler,它负责处理特定类型的...

    《ASP.NET开发实战详解:入门、模块、系统》程序代码

    接下来,书中会深入讲解ASP.NET的各个核心模块,如HttpModule和HttpHandler。HttpModule是处理HTTP请求的入口点,可以用于实现身份验证、日志记录等功能。HttpHandler则负责处理特定类型的请求,如处理图片或动态...

    ASP.NET源码——[论坛社区]中国技术论坛(仿Discuz).zip

    【ASP.NET 源码详解——打造中国技术论坛(仿Discuz)】 ASP.NET 是微软公司推出的一种基于.NET Framework的Web应用程序开发平台,它提供了丰富的功能和强大的性能,被广泛应用于构建动态网站、Web应用程序和服务。...

    【ASP.NET编程知识】基于asp.net MVC 应用程序的生命周期(详解).docx

    总结起来,ASP.NET MVC 应用程序的生命周期是一个复杂而有序的过程,从HttpApplication开始,经过HttpModule的预处理,到HttpHandler的最终处理,期间涉及路由、控制器选择、动作方法执行以及视图渲染等多个环节。...

    ASP生命周期

    5. **HttpModule与HttpHandler阶段** - **HttpModule**:HttpModule提供了事件处理机制,可以在ASP.NET请求的不同阶段执行代码。这些模块可以修改请求状态或响应内容,例如添加日志记录、安全验证等。 - **...

    基于ASP.NET的企业客户管理项目设计与实现cms项目设计与实现(源代码+录像演示).zip

    ASP.NET允许开发者进行性能优化,如使用Output Cache缓存页面、异步处理以提高响应速度,以及利用HttpModule和HttpHandler进行自定义处理。 通过这个项目,开发者不仅可以学习到ASP.NET的基础知识,还能了解到如何...

    Community Server专题.pdf

    ### 三、HttpModule与HttpHandler #### HttpModule HttpModule是在ASP.NET请求处理管道中的一个组件,它可以对HTTP请求进行预处理或后处理。在CS中,HttpModule可用于实现跨站点脚本(XSS)防护、日志记录、性能监控...

    ASP.NET源码——[电子商务]TLShop 网店系统.zip

    ASP.NET 提供的 HttpModule 和 HttpHandler 可用于处理支付回调,实现支付接口的无缝对接。 6. **前端模板与响应式设计**:TLShop 网店系统可能采用了HTML、CSS和JavaScript进行页面布局和交互设计。考虑到多设备...

    asp.net上海面试题目(经典)

    - ASP.NET如何处理HTTP请求,包括HttpApplication、HttpModule和HttpHandler的概念。 - 页面间的跳转和查询字符串管理。 4. 数据访问: - ADO.NET:数据库连接、数据读取器和数据适配器的使用。 - LINQ to SQL...

    DoNet面试题(选择题)

    4. HttpHandler与HttpModule的区别: - A. 一个Http请求可以经历多个HttpModule和一个HttpHandler。 - B. 错误。HttpHandler是Http请求的最终处理者。 - C. 错误。HttpModule是请求处理链的一部分,但不是最终...

    Microsoft.Web.Infrastructure.rar

    在实际项目中,Microsoft.Web.Infrastructure常被用于创建自定义的HttpModule或HttpHandler,以实现特定的中间件功能,例如缓存管理、日志记录或者用户身份验证。 7. **最佳实践** 使用Microsoft.Web....

    asp.net面试题及答案

    【ASP.NET面试题及答案详解】 ASP.NET是微软公司推出的一种用于构建Web应用程序的技术,它基于.NET Framework,提供了丰富的功能和高效性能。在面试中,ASP.NET相关的问题常常被用来评估候选人的技能和经验。以下是...

    选课系统文件

    ASP.NET提供了诸如Output Cache、HttpModule和HttpHandler等工具来帮助提高性能。 9. **部署与扩展性** 最后,一个完整的选课系统还需要考虑到部署和扩展性。ASP.NET支持多种部署方式,如IIS服务器、Azure云服务等...

    基于ASP.NET的学生信息管理系统工程

    此外,ASP.NET的模块化设计使得系统易于扩展,可以通过添加自定义HttpModule和HttpHandler来增强功能。 8. **错误处理与调试**:ASP.NET提供了丰富的错误处理机制,如全局错误处理、自定义错误页面等,便于调试和...

    ASP.NET源码——[电子商务]快乐商城全站源码.zip

    3. **订单处理**:从下单到支付完成,涉及订单创建、支付接口集成(如支付宝、微信支付)、库存更新等,ASP.NET提供了诸如HttpModule、HttpHandler等扩展点,便于实现这些业务逻辑。 4. **商品展示**:商品分类、...

    C # 经典例子

    此示例可能涵盖了ASP.NET页面生命周期、控件事件处理、HttpModule和HttpHandler、状态管理、以及MVC模式的应用。学习这些内容有助于理解如何使用C#构建高效的Web应用程序。 3. Windows Forms(CS101SamplesWinForms...

    Asp.Net面试题大全

    10. **什么是HttpModule和HttpHandler?** HttpModule是IIS中的插件,可以捕获和处理HTTP请求,常用于身份验证、日志记录等功能。HttpHandler是处理特定HTTP请求的对象,比如处理图片或XML请求。 11. **谈谈Asp.Net...

Global site tag (gtag.js) - Google Analytics