扩展IHttpHandler
前面提到当请求进入到IIS,IIS转发给ISAPI后会根据文件的后缀名来决定将请求转发给对应的处理程序进行处理,当然一大部分的处理都是交给了AspNet_ISAPI 了。但是,AspNet_ISAPI 不可能对所有的文件都采用同一种处理方式,所以现在我们就来分析一下AspNet_ISAPI是怎么进一步对请求进行处理的。
打开IIS站点,找到处理处理程序映射,可以看到不同后缀的文件,处理程序也相应的不同。由此可见AspNet_ISAPI将请求分配给了不同的Handler进行处理。

那么这些handler是如何注册的呢?我们打开 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config目录下的web.config文件,找到httphandlers节点,根据不同后缀,.Net框架已经为我们配置了一些默认的Handler处理程序。
<httpHandlers>
<add path="eurl.axd" verb="*" type="System.Web.HttpNotFoundHandler" validate="True"/>
<add path="trace.axd" verb="*" type="System.Web.Handlers.TraceHandler" validate="True"/>
<add path="WebResource.axd" verb="GET" type="System.Web.Handlers.AssemblyResourceLoader" validate="True"/>
<add verb="*" path="*_AppService.axd" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="False"/>
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="False"/>
<add path="*.axd" verb="*" type="System.Web.HttpNotFoundHandler" validate="True"/>
<add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="True"/>
<add path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" validate="True"/>
<add path="*.asmx" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="False"/>
<add path="*.rem" verb="*" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" validate="False"/>
<add path="*.soap" verb="*" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" validate="False"/>
<add path="*.asax" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.ascx" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.master" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.skin" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.browser" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.sitemap" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.dll.config" verb="GET,HEAD" type="System.Web.StaticFileHandler" validate="True"/>
<add path="*.exe.config" verb="GET,HEAD" type="System.Web.StaticFileHandler" validate="True"/>
<add path="*.config" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.cs" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.csproj" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.vb" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.vbproj" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.webinfo" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.licx" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.resx" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.resources" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.mdb" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.vjsproj" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.java" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.jsl" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.ldb" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.ad" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.dd" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.ldd" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.sd" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.cd" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.adprototype" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.lddprototype" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.sdm" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.sdmDocument" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.mdf" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.ldf" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.exclude" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.refresh" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="False"/>
<add path="*.rules" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.xoml" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="False"/>
<add path="*.xamlx" verb="*" type="System.Xaml.Hosting.XamlHttpHandlerFactory, System.Xaml.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="False"/>
<add path="*.aspq" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.cshtm" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.cshtml" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.vbhtm" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.vbhtml" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*" verb="GET,HEAD,POST" type="System.Web.DefaultHttpHandler" validate="True"/>
<add path="*" verb="*" type="System.Web.HttpMethodNotAllowedHandler" validate="True"/>
</httpHandlers>
那么这些Handler 的执行时机是在什么时候呢?前面我们提到请求进入asp.net管道后创建了HttpApplication,接着执行一堆事件,每个事件完成自己的工作。因为在上面我们从IIS的处理程序映射图可以看出,当IIS7以上并且是集成模式的时候请求才交给了Handler进行处理,经典模式的处理程序是IsapiModule。所以我们可以理解为在管道处理事件中,有一些事件是只支持IIS7以上的。其中就有MapRequestHandler 事件,当请求执行到该事件时,MapRequesthandler事件负责制定具体的handler处理请求,例如处理.ashx一般处理程序,.aspx页面,处理结束后继续往下执行其他事件。
既然MapRequestHandler只支持IIS7集成模式,那么IIS6呢,其实IIS6 会根据URL路径或扩展名和匹配规则(配置文件设置或Routing配置)进行查找,创建并赋值给HttpContext.Handler属性,然后在PreRequestHandlerExecute事件后调用HttpContext.Handler属性的ProcessRequest或BeginProcesssRequest方法。
理解了HttpHandler的原理后,如果我们要自定义自己的Handler处理一些特殊的请求时,我们该怎么做呢?继续往下看。
要自定义自己的Handler处理程序,.Net框架为我们提供了IHttpHandler接口,我们需要定义一个类并实现IHttpHandler接口。
//
// 摘要:
// Defines the contract that ASP.NET implements to synchronously process HTTP Web
// requests using custom HTTP handlers.
public interface IHttpHandler
{
//
// 摘要:
// Gets a value indicating whether another request can use the System.Web.IHttpHandler
// instance.
//
// 返回结果:
// true if the System.Web.IHttpHandler instance is reusable; otherwise, false.
bool IsReusable { get; } //
// 摘要:
// Enables processing of HTTP Web requests by a custom HttpHandler that implements
// the System.Web.IHttpHandler interface.
//
// 参数:
// context:
// An System.Web.HttpContext object that provides references to the intrinsic server
// objects (for example, Request, Response, Session, and Server) used to service
// HTTP requests.
void ProcessRequest(HttpContext context);
}
接下来我们定义一个ImageHandler类,该类实现IHttpHandler接口。
namespace Jesen.Web.Core.HttpHandler
{
/// <summary>
/// 自定义图片处理程序,通过Request请求中的UrlReferrer来判断是否是自己的站点所请求的,以此来防盗链
/// </summary>
public class ImageHandler : IHttpHandler
{
#region IHttpHandler Members public bool IsReusable
{
get { return true; }
} public void ProcessRequest(HttpContext context)
{
if (context.Request.UrlReferrer == null || context.Request.UrlReferrer.Host == null)
{
context.Response.ContentType = "image/JPEG";
context.Response.WriteFile("/Content/Image/Forbidden.jpg");
}
else
{
if (context.Request.UrlReferrer.Host.Contains("localhost"))
{
string FileName = context.Server.MapPath(context.Request.FilePath);
context.Response.ContentType = "image/JPEG";
context.Response.WriteFile(FileName);
}
else
{
context.Response.ContentType = "image/JPEG";
context.Response.WriteFile("/Content/Image/Forbidden.jpg");
}
}
} #endregion
}
}
现在我们已经准备好了一个Handler处理程序,接下来要做的就是在配置文件里面配置它,verb为请求方式POST/GET/HEAD等,type为类名,程序集名。
<system.webServer>
<handlers>
<add name="gif" path="*.gif" verb="*" type="Jesen.Web.Core.HttpHandler.ImageHandler,Jesen.Web.Core" />
<add name="png" path="*.png" verb="*" type="Jesen.Web.Core.HttpHandler.ImageHandler,Jesen.Web.Core" />
<add name="jpg" path="*.jpg" verb="*" type="Jesen.Web.Core.HttpHandler.ImageHandler,Jesen.Web.Core" />
<add name="jpeg" path="*.jpeg" verb="*" type="Jesen.Web.Core.HttpHandler.ImageHandler,Jesen.Web.Core" /> </handlers>
</system.webServer>
接着我们运行它,如果是采用MVC的,需要在路由注册时忽略它,在RouteConfig中添加 routes.IgnoreRoute("Handler/{*pathInfo}"); 便可以通过/Handler/123.jpg来访问。
.Net框架也提供了IHttpHandlerFactory接口,通过注册HandlerFactory,可以为不同的后缀指定不同的handler。
public class ImageHandlerFactory : IHttpHandlerFactory
{
public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
string path = context.Request.PhysicalPath;
if (Path.GetExtension(path).Equals(".gif"))
{
return new GifHandler();
}
else if (Path.GetExtension(path) == ".png")
{
return new PngHandler();
}
else
{
return new ImageHandler();
}
} public void ReleaseHandler(IHttpHandler handler)
{
}
}
<system.webServer>
<handlers>
<add name="imagefactory" path="*.gif,*.png,*.jpg,*.jpeg" verb="*" type="Jesen.Web.Core.HttpHandler.ImageHandlerFactory,Jesen.Web.Core" /> </handlers>
</system.webServer>
到此,httphandler的扩展就介绍到这里,下一篇来介绍MVC中的Handler。
扩展IHttpHandler的更多相关文章
- MVC路由 路由的三种扩展 替换MVC内置的Handler
Global.asax 是 程序入口文件 路由配置 为什么localhost:8088/Home/Index/1 能返问到我们写的 会去掉前缀跟端口号 变成Home/Index/1 用这个跟路由 ...
- 通过IHttpModule,IHttpHandler扩展IIS
IIS对Http Request的处理流程 当Windows Server收到从浏览器发送过来的http请求,处理流程如下(引用自官方文档): 最终请求会被w3wp.exe处理,处理过程如下: 左边蓝 ...
- 17+个ASP.NET MVC扩展点【附源码】
1.自定义一个HttpModule,并将其中的方法添加到HttpApplication相应的事件中!即:创建一个实现了IHttpmodule接口的类,并将配置WebConfig. 在自定义的Http ...
- 一步一步实战扩展 ASP.NET Route,实现小写 URL、个性化 URL
介绍 不知道大家在使用 ASP.NET MVC 时有没有一些扩展要求,反正我是有很多.在使用 MVC 这几年(PS:我是从 1.0 开始学,2.0.3.0 开发至今),我深深地觉得 MVC 的扩展性真 ...
- 【IHttpHandler】ASP.NET 生命周期
对由 Microsoft® Internet 信息服务 (IIS) 处理的 Microsoft® ASP.NET 页面的每个请求都会被移交到 ASP.NET HTTP 管道.HTTP 管道由一系列托管 ...
- Asp.net MVC Bundle 的使用与扩展
一.Asp.net 自带Bundle的使用: 1. 在Globale中注册与配置 BundleConfig.RegisterBundles(BundleTable.Bundles); public c ...
- IHttpModule与IHttpHandler的区别整理
IHttpModule与IHttpHandler的区别整理1.先后次序.先IHttpModule,后IHttpHandler. 注:Module要看你响应了哪个事件,一些事件是在Handler之前运行 ...
- MVC源码分析 - Controller创建和创建扩展
上一篇, 出现了一个至关重要的类:MvcHandler, 接下来就来看一下MvcHandler吧. 先不看具体方法, 先看一下类里面的情况. //这里实现了两个重要的接口, 异步处理和同步处理的接口p ...
- kindeditor扩展粘贴图片功能&修改图片上传路径并通过webapi上传图片到图片服务器
前言 kindeditor是一个非常好用的富文本编辑器,它的简单使用我就不再介绍了. 而kindeditor却对图片的处理不够理想. 本篇博文需要解决的问题有两个: kindeditor扩展粘贴图片功 ...
随机推荐
- E20180225-hm-xa
variation n. 变化,变动; 变异,演变; 变奏曲; 变量; auxiliary adj. 辅助的 subscript adj. 下标的,写在下方的,脚注的; n. 下标,脚注,下角数 ...
- Tinkoff Challenge - Elimination Round C. Mice problem(模拟)
传送门 题意 给出一个矩形的左下角和右上角的坐标,给出n个点的初始坐标和运动速度和方向,询问是否存在一个时间使得所有点都在矩形内,有则输出最短时间,否则输出-1 分析 对于每个点如果运动过程中都不在矩 ...
- Word Cloud (词云) - R
在前面已经陆续总结了如何用 Python 和 JavaScript 创建词云了,今天要说的是 R.其实 SPSS 和 SAS 的 Word Cloud 扩展模板都是基于 R 实现的. >> ...
- vultr 购买vps
基本安装转自:https://github.com/uxh/shadowsocks_bash/wiki/Vultr%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B 连接 Vul ...
- 实现简单版的LinkedList
相比ArrayList,双链表的数据结构就复杂多了,想要弄清代码的意思还是要搞清数据结构层面的变化. package cn.sp.chapter03; import java.util.Concurr ...
- Kruskal HDOJ 4313 Matrix
题目传送门 题意:如何花最小的代价使得一棵树划分开且不含同类节点 分析:当一条边连接的左右集合同类点小于等于1,那么不用删除,将两个集合合并,要求最小代价,那么贪心思想将权值降序排序,删除后剩下的就是 ...
- Application,Service,Activity 三者的Context的应用场景
Application 的 context 不是万能的,所以也不能随便乱用,对于有些地方则必须使用 Activity 的 Context, 对于Application,Service,Activity ...
- c#如何使用replace函数将"\"替换成"\\"
当我使用 String str="c:\aa.xls"; str=str.Replace("\","\\");时,括号为红色错误的,那么如何 ...
- robot framework 入门
obot framework 入门 2012-12-23 12:47:16 分类: LINUX 其实我不喜欢动不动就框架,动不动就架构,整出一坨专业术语搞的玄而又玄,让人云山雾绕,我想做的事情 ...
- fix for 12c profile
.for CDBS run as sysDBa CREATE OR REPLACE FUNCTION verify_function (username varchar2, password varc ...