前面提到当请求进入到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的更多相关文章

  1. MVC路由 路由的三种扩展 替换MVC内置的Handler

    Global.asax 是 程序入口文件 路由配置   为什么localhost:8088/Home/Index/1 能返问到我们写的 会去掉前缀跟端口号  变成Home/Index/1 用这个跟路由 ...

  2. 通过IHttpModule,IHttpHandler扩展IIS

    IIS对Http Request的处理流程 当Windows Server收到从浏览器发送过来的http请求,处理流程如下(引用自官方文档): 最终请求会被w3wp.exe处理,处理过程如下: 左边蓝 ...

  3. 17+个ASP.NET MVC扩展点【附源码】

    1.自定义一个HttpModule,并将其中的方法添加到HttpApplication相应的事件中!即:创建一个实现了IHttpmodule接口的类,并将配置WebConfig.  在自定义的Http ...

  4. 一步一步实战扩展 ASP.NET Route,实现小写 URL、个性化 URL

    介绍 不知道大家在使用 ASP.NET MVC 时有没有一些扩展要求,反正我是有很多.在使用 MVC 这几年(PS:我是从 1.0 开始学,2.0.3.0 开发至今),我深深地觉得 MVC 的扩展性真 ...

  5. 【IHttpHandler】ASP.NET 生命周期

    对由 Microsoft® Internet 信息服务 (IIS) 处理的 Microsoft® ASP.NET 页面的每个请求都会被移交到 ASP.NET HTTP 管道.HTTP 管道由一系列托管 ...

  6. Asp.net MVC Bundle 的使用与扩展

    一.Asp.net 自带Bundle的使用: 1. 在Globale中注册与配置 BundleConfig.RegisterBundles(BundleTable.Bundles); public c ...

  7. IHttpModule与IHttpHandler的区别整理

    IHttpModule与IHttpHandler的区别整理1.先后次序.先IHttpModule,后IHttpHandler. 注:Module要看你响应了哪个事件,一些事件是在Handler之前运行 ...

  8. MVC源码分析 - Controller创建和创建扩展

    上一篇, 出现了一个至关重要的类:MvcHandler, 接下来就来看一下MvcHandler吧. 先不看具体方法, 先看一下类里面的情况. //这里实现了两个重要的接口, 异步处理和同步处理的接口p ...

  9. kindeditor扩展粘贴图片功能&修改图片上传路径并通过webapi上传图片到图片服务器

    前言 kindeditor是一个非常好用的富文本编辑器,它的简单使用我就不再介绍了. 而kindeditor却对图片的处理不够理想. 本篇博文需要解决的问题有两个: kindeditor扩展粘贴图片功 ...

随机推荐

  1. BZOJ2874 训练士兵 主席树

    [啊 首先 这是道权限题,然后本人显然是没有权限的  23咳3] 最近数据结构做的越来越少..然后 就跟上次一样 ,一做就是三四种不同写法. 等价的题面: 最近GY大神在sc2的天梯中被神族虐得很惨, ...

  2. linux块设备模型架构框架

    Linux块设备的原理远比字符设备要复杂得多,尽管在linux这一块的方法论有很多相似之处,但考虑到它是用中块结构,它常常要搭配内存页管理,页缓冲块缓冲来改善硬盘访问的速度,按照块硬件最大的性能要求进 ...

  3. 初探js闭包

    1.变量的作用域:全局变量.局部变量 函数内部可以直接读取局部变量 js代码 var n=2; function fun(){ alert(n); } fun();  //2 函数外部不能读取函数内部 ...

  4. 安装phpwind报错

    在安装phpwind时,下面的报错提示是什么原因呢?  答:数据库密码应设置为空

  5. Ubuntu adb devices :???????????? no permissions 解决方法[转]

    转自: http://www.cnblogs.com/cat-lee/archive/2011/07/09/2101718.html untun下USB连接Android手机后,使用adb devic ...

  6. P2210 Haywire(A*)

    P2210 Haywire 题目描述 Farmer John有N只奶牛,(4 <= N <= 12,其中N是偶数). 他们建立了一套原生的系统,使得奶牛与他的朋友可以通过由干草保护的线路来 ...

  7. 《Windows核心编程系列》十谈谈同步设备IO与异步设备IO之异步IO

    同步设备IO与异步设备IO之异步IO介绍 设备IO与cpu速度甚至是内存访问相比较都是比较慢的,而且更不可预测.虽然如此,通过使用异步设备IO我们仍然能够创造出更高效的程序. 同步IO时,发出IO请求 ...

  8. 为什么JAVA虚拟机分为线程共享和非线程共享?

    大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) , VM Stack(虚拟 ...

  9. rhel7安装oracle 11gR2,所需的依赖包

    binutils-2.23.52.0.1-30.el7.x86_64 compat-libstdc++-33-3.2.3-61.x86_64compat-libstdc++-33-3.2.3-61.i ...

  10. Java8-Lomda表达式

    Lomda表达式 /** * All rights Reserved, Designed By www.bingo.com * @Title TestLamda.java * @author yang ...