HttpHandler

HttpHandler实现了ISAPI Extention的功能,他处理请求(Request)的信息和发送响应(Response)HttpHandler功能的实现通过实现IHttpHandler接口来达到。

看图先:

%7B980896B5-4116-45D2-8229-274846B37A69%7D0.jpg

ASP.NET 管道处理的末端是HTTP Hander,其实每个Asp.netPage都实现了IHttpHander,在VS.net中的对象察看器中你可以证实这一点

%7BA375FAAB-5302-4E76-9FA4-E8F6F9B79E7E%7D0.jpg

具体的类是这样定义的:public class Page : TemplateControl, IhttpHandler

接口IHttpHandler的定义如下:

 

None.gif interface  IHttpHandler
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif
void ProcessRequest(HttpContext ctx);
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
bool IsReuseable dot.gifget; }
InBlock.gif
ExpandedBlockEnd.gif}

None.gif

接口中

ProcessRequest 是添加自己的代码进行相应处理的地方。 IsReuseable 属性指明该 HttpHandler 的实现类是否需要缓存。

CS中有很多继承IHttpHandler接口的类,我取出有代表性而又容易理解的一个做分析:找到CommunityServerComponents项目Components目录下的Redirect.cs文件,内容如下:

None.gif // ------------------------------------------------------------------------------
None.gif
//  <copyright company="Telligent Systems">
None.gif
//      Copyright (c) Telligent Systems Corporation.  All rights reserved.
None.gif
//  </copyright> 
None.gif
// ------------------------------------------------------------------------------
None.gif

None.gif
using  System;
None.gif
using  System.Web;
None.gif
None.gif
namespace  CommunityServer.Components
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// Summary description for Redirect.
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    public class Redirect : IHttpHandler
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
public Redirect()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//
InBlock.gif            
// TODO: Add constructor logic here
InBlock.gif            
//
ExpandedSubBlockEnd.gif
        }

InBlock.gif
InBlock.gif        
public void ProcessRequest(HttpContext context)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
string url = context.Request.QueryString["u"];
InBlock.gif            
if(!Globals.IsNullorEmpty(url))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                context.Response.Redirect(url);
InBlock.gif                
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                context.Response.Redirect(Globals.GetSiteUrls().Home);
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            context.Response.End();
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public bool IsReusable
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn false; }
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif

这里的Redirect功能是在web请求满足HttpHandler配置文件中预设条件下自动拦截执行的,在web.config<httpHandlers>节点下可以看到

None.gif < add  verb ="GET"  path ="Utility/redirect.aspx"  type ="CommunityServer.Components.Redirect, CommunityServer.Components"   />


对该类的配置

· verb可以是"GET""POST",表示对GETPOST的请求进行处理。"*"表示对所有请求进行处理,这里是对GET请求进行处理。

· path指明对相应的文件进行处理,"*.aspx"表示对发给所有ASPX页面的请求进行处理,这里单独对redirect.aspx页面进行处理。可以指明路径,如"blogs"。表明只对blogs目录下的redirect.aspx文件请求进行处理。

· type属性中,逗号前的字符串指明HttpHandler的实现类的类名,后面的字符串指明Dll文件的名称。

实际处理是怎么样的呢?其实redirect.aspx页面在CS项目中并不存在,CS把对redirect.aspx的请求处理交给了CommunityServer.Components.dll程序集中Redirect类进行处理。处理的过程是执行

public void ProcessRequest(HttpContext context)

方法(Redirect类下的ProcessRequest方法是对当前请求的上下文ContextUrl是否包含“u”参数,如果有并且参数值不为null就调用Response.Redirect方法跳转到“u”参数值所执行的页面,如果没有参数或者参数值为空就跳转到CS的首页)

另外在CS中对RSSTrackback的处理都使用了httpHandler的处理方式。

前面提到,所有页面的基类Page都实现了HttpHandler接口,因此每个asp.net的页面都可以看成是一个HttpHandler处理类,只是配置部分在machine.config

 

None.gif < httpHandlers >
None.gif            
< add  verb ="*"  path ="*.vjsproj"  type ="System.Web.HttpForbiddenHandler" />< add  verb ="*"  path ="*.java"  type ="System.Web.HttpForbiddenHandler" />< add  verb ="*"  path ="*.jsl"  type ="System.Web.HttpForbiddenHandler" />< add  verb ="*"  path ="trace.axd"  type ="System.Web.Handlers.TraceHandler" />
None.gif            
< add  verb ="*"  path ="*.aspx"  type ="System.Web.UI.PageHandlerFactory" />
None.gif            
< add  verb ="*"  path ="*.ashx"  type ="System.Web.UI.SimpleHandlerFactory" />
None.gif            
< add  verb ="*"  path ="*.asmx"  type ="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"  validate ="false" />
None.gif            
< add  verb ="*"  path ="*.rem"  type ="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"  validate ="false" />
None.gif            
< add  verb ="*"  path ="*.soap"  type ="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"  validate ="false" />
None.gif            
< add  verb ="*"  path ="*.asax"  type ="System.Web.HttpForbiddenHandler" />
None.gif            
< add  verb ="*"  path ="*.ascx"  type ="System.Web.HttpForbiddenHandler" />
None.gif            
< add  verb ="GET,HEAD"  path ="*.dll.config"  type ="System.Web.StaticFileHandler" />
None.gif            
< add  verb ="GET,HEAD"  path ="*.exe.config"  type ="System.Web.StaticFileHandler" />
None.gif            
< add  verb ="*"  path ="*.config"  type ="System.Web.HttpForbiddenHandler" />
None.gif            
< add  verb ="*"  path ="*.cs"  type ="System.Web.HttpForbiddenHandler" />
None.gif            
< add  verb ="*"  path ="*.csproj"  type ="System.Web.HttpForbiddenHandler" />
None.gif            
< add  verb ="*"  path ="*.vb"  type ="System.Web.HttpForbiddenHandler" />
None.gif            
< add  verb ="*"  path ="*.vbproj"  type ="System.Web.HttpForbiddenHandler" />
None.gif            
< add  verb ="*"  path ="*.webinfo"  type ="System.Web.HttpForbiddenHandler" />
None.gif            
< add  verb ="*"  path ="*.asp"  type ="System.Web.HttpForbiddenHandler" />
None.gif            
< add  verb ="*"  path ="*.licx"  type ="System.Web.HttpForbiddenHandler" />
None.gif            
< add  verb ="*"  path ="*.resx"  type ="System.Web.HttpForbiddenHandler" />
None.gif            
< add  verb ="*"  path ="*.resources"  type ="System.Web.HttpForbiddenHandler" />
None.gif            
< add  verb ="GET,HEAD"  path ="*"  type ="System.Web.StaticFileHandler" />
None.gif            
< add  verb ="*"  path ="*"  type ="System.Web.HttpMethodNotAllowedHandler" />
None.gif        
</ httpHandlers >
 

借助一个工具:Reflector,看看Page类下的HttpHandler处理方法ProcessRequest都做了什么

None.gif [EditorBrowsable(EditorBrowsableState.Never)]
None.gif
public   void  ProcessRequest(HttpContext context)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif      
this.SetIntrinsics(context);
InBlock.gif      
this.ProcessRequest();
ExpandedBlockEnd.gif}

None.gif
private   void  SetIntrinsics(HttpContext context)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif      
this._context = context;
InBlock.gif      
this._request = context.Request;
InBlock.gif      
this._response = context.Response;
InBlock.gif      
this._application = context.Application;
InBlock.gif      
this._cache = context.Cache;
InBlock.gif      
if ((this._clientTarget != null&& (this._clientTarget.Length > 0))
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            
this._request.ClientTarget = this._clientTarget;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
base.HookUpAutomaticHandlers();
ExpandedBlockEnd.gif}

None.gif
private   void  ProcessRequest()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif      Thread thread1 
= Thread.CurrentThread;
InBlock.gif      CultureInfo info1 
= thread1.CurrentCulture;
InBlock.gif      CultureInfo info2 
= thread1.CurrentUICulture;
InBlock.gif      
this.FrameworkInitialize();
InBlock.gif      
try
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  
if (this.IsTransacted)
ExpandedSubBlockStart.gifContractedSubBlock.gif                  
dot.gif{
InBlock.gif                        
this.ProcessRequestTransacted();
ExpandedSubBlockEnd.gif                  }

InBlock.gif                  
else
ExpandedSubBlockStart.gifContractedSubBlock.gif                  
dot.gif{
InBlock.gif                        
this.ProcessRequestMain();
ExpandedSubBlockEnd.gif                  }

InBlock.gif                  
this.ProcessRequestEndTrace();
ExpandedSubBlockEnd.gif            }

InBlock.gif            
finally
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  
this.ProcessRequestCleanup();
InBlock.gif                  InternalSecurityPermissions.ControlThread.Assert();
InBlock.gif                  thread1.CurrentCulture 
= info1;
InBlock.gif                  thread1.CurrentUICulture 
= info2;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif      }

InBlock.gif      
catch
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            
throw;
ExpandedSubBlockEnd.gif      }

ExpandedBlockEnd.gif}

None.gif


 

Page类的ProcessRequest方法先是把上下文Context内容赋值到当前Page中的一些属性里,然后调用System.Web.UI.TemplateControl中的HookUpAutomaticHandlers()

None.gif internal   void  HookUpAutomaticHandlers()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif      
if (this.SupportAutoEvents)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            SimpleBitVector32 vector1 
= new SimpleBitVector32(this.AutoHandlers);
InBlock.gif            InternalSecurityPermissions.Reflection.Assert();
InBlock.gif            
if (!vector1[1])
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  vector1[
1= true;
InBlock.gif                  
this.GetDelegateInformation("Page_Init"ref vector1, 24);
InBlock.gif                  
this.GetDelegateInformation("Page_Load"ref vector1, 80x10);
InBlock.gif                  
this.GetDelegateInformation("Page_DataBind"ref vector1, 0x200x40);
InBlock.gif                  
this.GetDelegateInformation("Page_PreRender"ref vector1, 0x800x100);
InBlock.gif                  
this.GetDelegateInformation("Page_Unload"ref vector1, 0x2000x400);
InBlock.gif                  
this.GetDelegateInformation("Page_Error"ref vector1, 0x8000x1000);
InBlock.gif                  
this.GetDelegateInformation("Page_AbortTransaction"ref vector1, 0x20000x4000);
InBlock.gif                  
this.GetDelegateInformation("OnTransactionAbort"ref vector1, 0x80000x10000);
InBlock.gif                  
this.GetDelegateInformation("Page_CommitTransaction"ref vector1, 0x200000x40000);
InBlock.gif                  
this.GetDelegateInformation("OnTransactionCommit"ref vector1, 0x800000x100000);
InBlock.gif                  
this.AutoHandlers = vector1.Data;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
if (vector1[2])
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  
base.Init += this.GetDelegateFromMethodName("Page_Init", vector1[4]);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
if (vector1[8])
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  
base.Load += this.GetDelegateFromMethodName("Page_Load", vector1[0x10]);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
if (vector1[0x20])
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  
base.DataBinding += this.GetDelegateFromMethodName("Page_DataBind", vector1[0x40]);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
if (vector1[0x80])
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  
base.PreRender += this.GetDelegateFromMethodName("Page_PreRender", vector1[0x100]);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
if (vector1[0x200])
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  
base.Unload += this.GetDelegateFromMethodName("Page_Unload", vector1[0x400]);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
if (vector1[0x800])
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  
this.Error += this.GetDelegateFromMethodName("Page_Error", vector1[0x1000]);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
if (vector1[0x2000])
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  
this.AbortTransaction += this.GetDelegateFromMethodName("Page_AbortTransaction", vector1[0x4000]);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else if (vector1[0x8000])
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  
this.AbortTransaction += this.GetDelegateFromMethodName("OnTransactionAbort", vector1[0x10000]);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
if (vector1[0x20000])
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  
this.CommitTransaction += this.GetDelegateFromMethodName("Page_CommitTransaction", vector1[0x40000]);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else if (vector1[0x80000])
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  
this.CommitTransaction += this.GetDelegateFromMethodName("OnTransactionCommit", vector1[0x100000]);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif      }

ExpandedBlockEnd.gif}

None.gif
None.gif


方法连接一些Handlers,通过委托加载相关的事件进行页面的初始化工作。

我不再往下分析,整个Page页面很庞大,有兴趣的朋友自己慢慢研究,说这些只是要明白一点,任何一个Page页面都是HttpHandler,页面处理是从这里开始。



.Text的早期版本中(很久没有看.Text的代码了)安装时要配置IIS

%7B73C5C93C-8C60-4719-8C06-A6F0EC1DCCEE%7D0.jpg

asp.net管道处理的级别上对一些扩展名称做映射,如*.html(其实.Text是做了*.*ASP.NET映射,够狠!,该扩展名的文件原本直接由IIS提交给请求者而不会经过asp.net处理机制处理,因此asp.net管道中的httpHandler是不可能拦截到的,但是只要做如下操作

%7BFD0B6595-97EA-4C61-A818-CD3D39919A74%7D0.jpg

这时,IIS会把对*.html文件的请求也交由ASP.NET机制去处理,继承IHttpHandler就可以拦截它(.Text中实际继承的是IHttpHandlerFactory)。有了这些知识就不难理解为什么你在.Text系统下察看blog时请求的是html文件(其实请求的html文件根本就不存在),返回的信息确是动态页面的内容,这与大型CMS系统不同,并不是为了节约系统资源预先生成htmlDotText之所以这样做牵涉到PermalinkSearch Engine Friendly,有这方面兴趣的朋友可以在google找到很多相关资源。


    虽然
CS中的blog.Text有密不可分的关系,但是CS中的blog已经没有采取早期.TextUrl扩展名为.html的访问机制,而是直接采用.aspx扩展名,也许更多考虑的是CS的部署问题,毕竟不是所有的CS使用者都会有可以自己配置IIS扩展名映射的权限,大多数虚拟主机也是不提供这样功能的。

HttpHandler还可以用来处理图片与下载的盗链问题,先在IIS中添加一些常用图片扩展名的映射到IIS中用Asp.net来处理对它的请求,这样就可以通过继承IHttpHandler的类和适当的配置来处理用户的请求,大致说一下过程:

在实现IHttpHandler接口的类中,ProcessRequest方法先用%7BB957E573-E146-4939-BD2E-38175F401A70%7D0.jpg判断上次请求的URL(为什么是判断上次请求的URL,请看我上一篇专题中对IIS运行过程的讲解),如果这个URL是在你限定内那么就调用Response.WriteFile方法输出文件,如果不是,你可以自己采取一些措施,比如输出一个带有警告字样的图片等等。当然,使用HttpHandler处理图片与下载盗链问题是需要IIS控制权限的,而且需要浪费一些系统资源。

转:http://www.cnblogs.com/ugoer/archive/2005/09/07/231676.html

转载于:https://www.cnblogs.com/han-xiao-feng/archive/2006/07/24/458145.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值