前面提到当请求进入到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. jQuery - AJAX 级联变动

    此篇文章主要是用来记忆使用JQUERY+AJAX技术实现 二级级联变动 : 当第一个下拉框变动时,第二个下拉列表框中也将会随之变动. JSP: ---------------------------- ...

  2. codeforces 689D D. Friends and Subsequences(RMQ+二分)

    题目链接: D. Friends and Subsequences time limit per test 2 seconds memory limit per test 512 megabytes ...

  3. 【JSOI 2007】祖玛

    [题目链接] 点击打开链接 [算法] f[i][j]表示第i段到第j段,最少需要多少次全部消除 那么,当color[i] = color[j]时 : 若s[i] + s[j] > 2,根据题目中 ...

  4. 【转】Vuex 学习总结

    对于很多新手来说,只是阅读文档是不好消化,我的建议是看看 vuex 的实例,通过研究实例来学习vuex.这样就会好理解多了.如果还是不能理解,最好办法就是先把store 的四个属性:state, ge ...

  5. AutoIT: 捕捉路由器登陆的小例子

    $url2 = "AX.XXX.XXX.COM" $oIE = _IECreate ($url2, , , , ) Sleep() ControlSetText('[REGEXPT ...

  6. ==和equals()的不同点

    两者都可以用于对象的比较."=="用于比较两个对象的内存地址值(引用值)是否相等,equals()方法用于比较两个对象的内容是否一致. String str1 = new Stri ...

  7. HDU 5912 Fraction (模拟)

    题意:给定一个分式,让你化简. 析:从分母开始模拟分数的算法,最后约分. 代码如下: #pragma comment(linker, "/STACK:1024000000,102400000 ...

  8. SpringBoot使用MongoDB

    一.什么是MongoDB MongoDB是一个基于分布式文件存储的数据库,由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之间的 ...

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

    同步设备IO 所谓同步IO是指线程在发起IO请求后会被挂起,IO完成后继续执行. 异步IO是指:线程发起IO请求后并不会挂起而是继续执行.IO完毕后会得到设备的通知.而IO完成端口就是实现这种通知的很 ...

  10. Lightoj 1090 - Trailing Zeroes (II)

    题目连接: http://www.lightoj.com/volume_showproblem.php?problem=1090 题目大意: 给出n,r,p,q四个数字1<=n,r,p,q< ...