Community Server
专题四:HttpHandler
HttpHandler实现了ISAPI Extention的功能,他处理请求(Request)的信息和发送响应(Response)。HttpHandler功能的实现通过实现IHttpHandler接口来达到。
看图先:
在ASP.NET 管道处理的末端是HTTP Hander,其实每个Asp.net的Page都实现了IHttpHander,在VS.net中的对象察看器中你可以证实这一点
具体的类是这样定义的:public class Page : TemplateControl, IhttpHandler。
接口IHttpHandler的定义如下:
ProcessRequest是添加自己的代码进行相应处理的地方。IsReuseable属性指明该HttpHandler的实现类是否需要缓存。
interface
IHttpHandler
{
voidProcessRequest(HttpContextctx);
boolIsReuseable{get;}
}
接口中
在CS中有很多继承IHttpHandler接口的类,我取出有代表性而又容易理解的一个做分析:找到CommunityServerComponents项目Components目录下的Redirect.cs文件,内容如下:
这里的Redirect功能是在
web请求满足HttpHandler配置文件中预设条件下自动拦截执行的,在web.config中<httpHandlers>节点下可以看到
//
------------------------------------------------------------------------------
//
<copyrightcompany="TelligentSystems">
//
Copyright(c)TelligentSystemsCorporation.Allrightsreserved.
//
</copyright>
//
------------------------------------------------------------------------------
using
System;
using
System.Web;
namespace
CommunityServer.Components
{
/**////<summary>
///SummarydescriptionforRedirect.
///</summary>
publicclassRedirect:IHttpHandler
{
publicRedirect()
{
//
//TODO:Addconstructorlogichere
//
}
publicvoidProcessRequest(HttpContextcontext)
{
stringurl=context.Request.QueryString["u"];
if(!Globals.IsNullorEmpty(url))
{
context.Response.Redirect(url);
}
else
{
context.Response.Redirect(Globals.GetSiteUrls().Home);
}
context.Response.End();
}
publicboolIsReusable
{
get{returnfalse;}
}
}
}
<
add
verb
="GET"
path
="Utility/redirect.aspx"
type
="CommunityServer.Components.Redirect,CommunityServer.Components"
/>
对该类的配置
·
verb可以是"GET"或"POST",表示对GET或POST的请求进行处理。"*"表示对所有请求进行处理,这里是对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方法是对当前请求的上下文Context中Url是否包含“u”参数,如果有并且参数值不为null就调用Response.Redirect方法跳转到“u”参数值所执行的页面,如果没有参数或者参数值为空就跳转到CS的首页)。
另外在
CS中对RSS和Trackback的处理都使用了httpHandler的处理方式。
前面提到,所有页面的基类Page都实现了HttpHandler接口,因此每个asp.net的页面都可以看成是一个HttpHandler处理类,只是配置部分在machine.config中
借助一个工具:Reflector,看看Page类下的HttpHandler处理方法ProcessRequest
都做了什么
.Text的早期版本中(很久没有看.Text的代码了)安装时要配置IIS
[EditorBrowsable(EditorBrowsableState.Never)]
public
void
ProcessRequest(HttpContextcontext)
{
this.SetIntrinsics(context);
this.ProcessRequest();
}
private
void
SetIntrinsics(HttpContextcontext)
{
this._context=context;
this._request=context.Request;
this._response=context.Response;
this._application=context.Application;
this._cache=context.Cache;
if((this._clientTarget!=null)&&(this._clientTarget.Length>0))
{
this._request.ClientTarget=this._clientTarget;
}
base.HookUpAutomaticHandlers();
}
private
void
ProcessRequest()
{
Threadthread1=Thread.CurrentThread;
CultureInfoinfo1=thread1.CurrentCulture;
CultureInfoinfo2=thread1.CurrentUICulture;
this.FrameworkInitialize();
try
{
try
{
if(this.IsTransacted)
{
this.ProcessRequestTransacted();
}
else
{
this.ProcessRequestMain();
}
this.ProcessRequestEndTrace();
}
finally
{
this.ProcessRequestCleanup();
InternalSecurityPermissions.ControlThread.Assert();
thread1.CurrentCulture=info1;
thread1.CurrentUICulture=info2;
}
}
catch
{
throw;
}
}
在Page类的ProcessRequest方法先是把上下文Context内容赋值到当前Page中的一些属性里,然后调用System.Web.UI.TemplateControl中的HookUpAutomaticHandlers()
internal
void
HookUpAutomaticHandlers()
{
if(this.SupportAutoEvents)
{
SimpleBitVector32vector1=newSimpleBitVector32(this.AutoHandlers);
InternalSecurityPermissions.Reflection.Assert();
if(!vector1[1])
{
vector1[1]=true;
this.GetDelegateInformation("Page_Init",refvector1,2,4);
this.GetDelegateInformation("Page_Load",refvector1,8,0x10);
this.GetDelegateInformation("Page_DataBind",refvector1,0x20,0x40);
this.GetDelegateInformation("Page_PreRender",refvector1,0x80,0x100);
this.GetDelegateInformation("Page_Unload",refvector1,0x200,0x400);
this.GetDelegateInformation("Page_Error",refvector1,0x800,0x1000);
this.GetDelegateInformation("Page_AbortTransaction",refvector1,0x2000,0x4000);
this.GetDelegateInformation("OnTransactionAbort",refvector1,0x8000,0x10000);
this.GetDelegateInformation("Page_CommitTransaction",refvector1,0x20000,0x40000);
this.GetDelegateInformation("OnTransactionCommit",refvector1,0x80000,0x100000);
this.AutoHandlers=vector1.Data;
}
if(vector1[2])
{
base.Init+=this.GetDelegateFromMethodName("Page_Init",vector1[4]);
}
if(vector1[8])
{
base.Load+=this.GetDelegateFromMethodName("Page_Load",vector1[0x10]);
}
if(vector1[0x20])
{
base.DataBinding+=this.GetDelegateFromMethodName("Page_DataBind",vector1[0x40]);
}
if(vector1[0x80])
{
base.PreRender+=this.GetDelegateFromMethodName("Page_PreRender",vector1[0x100]);
}
if(vector1[0x200])
{
base.Unload+=this.GetDelegateFromMethodName("Page_Unload",vector1[0x400]);
}
if(vector1[0x800])
{
this.Error+=this.GetDelegateFromMethodName("Page_Error",vector1[0x1000]);
}
if(vector1[0x2000])
{
this.AbortTransaction+=this.GetDelegateFromMethodName("Page_AbortTransaction",vector1[0x4000]);
}
elseif(vector1[0x8000])
{
this.AbortTransaction+=this.GetDelegateFromMethodName("OnTransactionAbort",vector1[0x10000]);
}
if(vector1[0x20000])
{
this.CommitTransaction+=this.GetDelegateFromMethodName("Page_CommitTransaction",vector1[0x40000]);
}
elseif(vector1[0x80000])
{
this.CommitTransaction+=this.GetDelegateFromMethodName("OnTransactionCommit",vector1[0x100000]);
}
}
}
方法连接一些
Handlers
,通过委托加载相关的事件进行页面的初始化工作。
在
我不再往下分析,整个Page页面很庞大,有兴趣的朋
分享到:
评论