分享
 
 
 

我的收藏:Community Server专题四:HttpHandler

王朝other·作者佚名  2006-03-20
窄屏简体版  字體: |||超大  

原文地址:http://ugoer.cnblogs.com/archive/2005/09/07/231676.html

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

看图先:

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

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

接口IHttpHandler的定义如下:

interface IHttpHandler

{

void ProcessRequest(HttpContext ctx);

bool IsReuseable { get; }

}

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

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

//------------------------------------------------------------------------------

// <copyright company="Telligent Systems">

// Copyright (c) Telligent Systems Corporation. All rights reserved.

// </copyright>

//------------------------------------------------------------------------------

using System;

using System.Web;

namespace CommunityServer.Components

{

/**//// <summary>

/// Summary description for Redirect.

/// </summary>

public class Redirect : IHttpHandler

{

public Redirect()

{

//

// TODO: Add constructor logic here

//

}

public void ProcessRequest(HttpContext context)

{

string url = context.Request.QueryString["u"];

if(!Globals.IsNullorEmpty(url))

{

context.Response.Redirect(url);

}

else

{

context.Response.Redirect(Globals.GetSiteUrls().Home);

}

context.Response.End();

}

public bool IsReusable

{

get { return false; }

}

}

}

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

<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中

<httpHandlers>

<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"/>

<add verb="*" path="*.aspx" type="System.Web.UI.PageHandlerFactory"/>

<add verb="*" path="*.ashx" type="System.Web.UI.SimpleHandlerFactory"/>

<add verb="*" path="*.asmx" type="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" validate="false"/>

<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"/>

<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"/>

<add verb="*" path="*.asax" type="System.Web.HttpForbiddenHandler"/>

<add verb="*" path="*.ascx" type="System.Web.HttpForbiddenHandler"/>

<add verb="GET,HEAD" path="*.dll.config" type="System.Web.StaticFileHandler"/>

<add verb="GET,HEAD" path="*.exe.config" type="System.Web.StaticFileHandler"/>

<add verb="*" path="*.config" type="System.Web.HttpForbiddenHandler"/>

<add verb="*" path="*.cs" type="System.Web.HttpForbiddenHandler"/>

<add verb="*" path="*.csproj" type="System.Web.HttpForbiddenHandler"/>

<add verb="*" path="*.vb" type="System.Web.HttpForbiddenHandler"/>

<add verb="*" path="*.vbproj" type="System.Web.HttpForbiddenHandler"/>

<add verb="*" path="*.webinfo" type="System.Web.HttpForbiddenHandler"/>

<add verb="*" path="*.asp" type="System.Web.HttpForbiddenHandler"/>

<add verb="*" path="*.licx" type="System.Web.HttpForbiddenHandler"/>

<add verb="*" path="*.resx" type="System.Web.HttpForbiddenHandler"/>

<add verb="*" path="*.resources" type="System.Web.HttpForbiddenHandler"/>

<add verb="GET,HEAD" path="*" type="System.Web.StaticFileHandler"/>

<add verb="*" path="*" type="System.Web.HttpMethodNotAllowedHandler"/>

</httpHandlers>

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

[EditorBrowsable(EditorBrowsableState.Never)]

public void ProcessRequest(HttpContext context)

{

this.SetIntrinsics(context);

this.ProcessRequest();

}

private void SetIntrinsics(HttpContext context)

{

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()

{

Thread thread1 = Thread.CurrentThread;

CultureInfo info1 = thread1.CurrentCulture;

CultureInfo info2 = 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)

{

SimpleBitVector32 vector1 = new SimpleBitVector32(this.AutoHandlers);

InternalSecurityPermissions.Reflection.Assert();

if (!vector1[1])

{

vector1[1] = true;

this.GetDelegateInformation("Page_Init", ref vector1, 2, 4);

this.GetDelegateInformation("Page_Load", ref vector1, 8, 0x10);

this.GetDelegateInformation("Page_DataBind", ref vector1, 0x20, 0x40);

this.GetDelegateInformation("Page_PreRender", ref vector1, 0x80, 0x100);

this.GetDelegateInformation("Page_Unload", ref vector1, 0x200, 0x400);

this.GetDelegateInformation("Page_Error", ref vector1, 0x800, 0x1000);

this.GetDelegateInformation("Page_AbortTransaction", ref vector1, 0x2000, 0x4000);

this.GetDelegateInformation("OnTransactionAbort", ref vector1, 0x8000, 0x10000);

this.GetDelegateInformation("Page_CommitTransaction", ref vector1, 0x20000, 0x40000);

this.GetDelegateInformation("OnTransactionCommit", ref vector1, 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]);

}

else if (vector1[0x8000])

{

this.AbortTransaction += this.GetDelegateFromMethodName("OnTransactionAbort", vector1[0x10000]);

}

if (vector1[0x20000])

{

this.CommitTransaction += this.GetDelegateFromMethodName("Page_CommitTransaction", vector1[0x40000]);

}

else if (vector1[0x80000])

{

this.CommitTransaction += this.GetDelegateFromMethodName("OnTransactionCommit", vector1[0x100000]);

}

}

}

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

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

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

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

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

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

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

在实现IHttpHandler接口的类中,ProcessRequest方法先用

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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有