找回密码
 立即注册
首页 业界区 业界 细说 HttpHandler 的映射过程

细说 HttpHandler 的映射过程

荆邦 2025-5-29 16:03:07
在ASP.NET编程模型中,一个来自客户端的请求要经过一个称为管线的处理过程。在整个处理请求中,相对于其它对象来说,HttpHandler的处理算得上是整个过程的核心部分。由于HttpHandler的重要地位,我前面已经有二篇博客对它过一些使用上的介绍。【用Asp.net写自己的服务框架】中谈到了它的一般使用方法。【细说ASP.NET的各种异步操作】又详细地介绍了异步HttpHandler的使用方式。
今天的博客将着重介绍HttpHandler的配置,创建以及重用过程,还将涉及HttpHandlerFactory的内容。
回顾HttpHandler

HttpHandler其实是一类统称:泛指实现了IHttpHandler接口的一些类型,这些类型有一个共同的功能,那就是可以用来处理HTTP请求。IHttpHandler的接口定义如下:
  1. // 定义 ASP.NET 为使用自定义 HTTP 处理程序同步处理 HTTP Web 请求而实现的协定。
  2. public interface IHttpHandler
  3. {
  4. <httpHandlers>
  5. <httpHandlers>
  6. <httpHandlers>
  7.    
  8. </httpHandlers>
  9. </httpHandlers>
  10. </httpHandlers>// 获取一个值,该值指示其他请求是否可以使用 System.Web.IHttpHandler 实例。
  11. <httpHandlers>
  12. <httpHandlers>
  13. <httpHandlers>
  14.    
  15. </httpHandlers>
  16. </httpHandlers>
  17. </httpHandlers>//
  18. <httpHandlers>
  19. <httpHandlers>
  20. <httpHandlers>
  21.    
  22. </httpHandlers>
  23. </httpHandlers>
  24. </httpHandlers>// 返回结果:
  25. <httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>//<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers> 如果 System.Web.IHttpHandler 实例可再次使用,则为 true;否则为 false。
  38. <httpHandlers>
  39. <httpHandlers>
  40. <httpHandlers>
  41.    
  42. </httpHandlers>
  43. </httpHandlers>
  44. </httpHandlers>bool IsReusable { get; }
  45. <httpHandlers>
  46. <httpHandlers>
  47. <httpHandlers>
  48.    
  49. </httpHandlers>
  50. </httpHandlers>
  51. </httpHandlers>// 通过实现 System.Web.IHttpHandler 接口的自定义 HttpHandler 启用 HTTP Web 请求的处理。
  52. <httpHandlers>
  53. <httpHandlers>
  54. <httpHandlers>
  55.    
  56. </httpHandlers>
  57. </httpHandlers>
  58. </httpHandlers>void ProcessRequest(HttpContext context);
  59. }
复制代码
有关HttpHandler的各类用法,可参考我的博客【用Asp.net写自己的服务框架】,本文将不再重复说明了。它还有一个异步版本:
  1. // 摘要:
  2. //<httpHandlers>
  3. <httpHandlers>
  4. <httpHandlers>
  5.    
  6. </httpHandlers>
  7. </httpHandlers>
  8. </httpHandlers> 定义 HTTP 异步处理程序对象必须实现的协定。
  9. public interface IHttpAsyncHandler : IHttpHandler
  10. {
  11. <httpHandlers>
  12. <httpHandlers>
  13. <httpHandlers>
  14.    
  15. </httpHandlers>
  16. </httpHandlers>
  17. </httpHandlers>// 摘要:
  18. <httpHandlers>
  19. <httpHandlers>
  20. <httpHandlers>
  21.    
  22. </httpHandlers>
  23. </httpHandlers>
  24. </httpHandlers>//<httpHandlers>
  25. <httpHandlers>
  26. <httpHandlers>
  27.    
  28. </httpHandlers>
  29. </httpHandlers>
  30. </httpHandlers> 启动对 HTTP 处理程序的异步调用。
  31. <httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers>//
  38. <httpHandlers>
  39. <httpHandlers>
  40. <httpHandlers>
  41.    
  42. </httpHandlers>
  43. </httpHandlers>
  44. </httpHandlers>// 参数:
  45. <httpHandlers>
  46. <httpHandlers>
  47. <httpHandlers>
  48.    
  49. </httpHandlers>
  50. </httpHandlers>
  51. </httpHandlers>//   context:
  52. <httpHandlers>
  53. <httpHandlers>
  54. <httpHandlers>
  55.    
  56. </httpHandlers>
  57. </httpHandlers>
  58. </httpHandlers>//<httpHandlers>
  59. <httpHandlers>
  60. <httpHandlers>
  61.    
  62. </httpHandlers>
  63. </httpHandlers>
  64. </httpHandlers> 一个 System.Web.HttpContext 对象,该对象提供对用于向 HTTP 请求提供服务的内部服务器对象(如 Request、Response、Session
  65. <httpHandlers>
  66. <httpHandlers>
  67. <httpHandlers>
  68.    
  69. </httpHandlers>
  70. </httpHandlers>
  71. </httpHandlers>//<httpHandlers>
  72. <httpHandlers>
  73. <httpHandlers>
  74.    
  75. </httpHandlers>
  76. </httpHandlers>
  77. </httpHandlers> 和 Server)的引用。
  78. <httpHandlers>
  79. <httpHandlers>
  80. <httpHandlers>
  81.    
  82. </httpHandlers>
  83. </httpHandlers>
  84. </httpHandlers>//
  85. <httpHandlers>
  86. <httpHandlers>
  87. <httpHandlers>
  88.    
  89. </httpHandlers>
  90. </httpHandlers>
  91. </httpHandlers>//   extraData:
  92. <httpHandlers>
  93. <httpHandlers>
  94. <httpHandlers>
  95.    
  96. </httpHandlers>
  97. </httpHandlers>
  98. </httpHandlers>//<httpHandlers>
  99. <httpHandlers>
  100. <httpHandlers>
  101.    
  102. </httpHandlers>
  103. </httpHandlers>
  104. </httpHandlers> 处理该请求所需的所有额外数据。
  105. <httpHandlers>
  106. <httpHandlers>
  107. <httpHandlers>
  108.    
  109. </httpHandlers>
  110. </httpHandlers>
  111. </httpHandlers>//
  112. <httpHandlers>
  113. <httpHandlers>
  114. <httpHandlers>
  115.    
  116. </httpHandlers>
  117. </httpHandlers>
  118. </httpHandlers>//   cb:
  119. <httpHandlers>
  120. <httpHandlers>
  121. <httpHandlers>
  122.    
  123. </httpHandlers>
  124. </httpHandlers>
  125. </httpHandlers>//<httpHandlers>
  126. <httpHandlers>
  127. <httpHandlers>
  128.    
  129. </httpHandlers>
  130. </httpHandlers>
  131. </httpHandlers> 异步方法调用完成时要调用的 System.AsyncCallback。如果 cb 为 null,则不调用委托。
  132. <httpHandlers>
  133. <httpHandlers>
  134. <httpHandlers>
  135.    
  136. </httpHandlers>
  137. </httpHandlers>
  138. </httpHandlers>//
  139. <httpHandlers>
  140. <httpHandlers>
  141. <httpHandlers>
  142.    
  143. </httpHandlers>
  144. </httpHandlers>
  145. </httpHandlers>// 返回结果:
  146. <httpHandlers>
  147. <httpHandlers>
  148. <httpHandlers>
  149.    
  150. </httpHandlers>
  151. </httpHandlers>
  152. </httpHandlers>//<httpHandlers>
  153. <httpHandlers>
  154. <httpHandlers>
  155.    
  156. </httpHandlers>
  157. </httpHandlers>
  158. </httpHandlers> 包含有关进程状态信息的 System.IAsyncResult。
  159. <httpHandlers>
  160. <httpHandlers>
  161. <httpHandlers>
  162.    
  163. </httpHandlers>
  164. </httpHandlers>
  165. </httpHandlers>IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData);
  166. <httpHandlers>
  167. <httpHandlers>
  168. <httpHandlers>
  169.    
  170. </httpHandlers>
  171. </httpHandlers>
  172. </httpHandlers>//
  173. <httpHandlers>
  174. <httpHandlers>
  175. <httpHandlers>
  176.    
  177. </httpHandlers>
  178. </httpHandlers>
  179. </httpHandlers>// 摘要:
  180. <httpHandlers>
  181. <httpHandlers>
  182. <httpHandlers>
  183.    
  184. </httpHandlers>
  185. </httpHandlers>
  186. </httpHandlers>//<httpHandlers>
  187. <httpHandlers>
  188. <httpHandlers>
  189.    
  190. </httpHandlers>
  191. </httpHandlers>
  192. </httpHandlers> 进程结束时提供异步处理 End 方法。
  193. <httpHandlers>
  194. <httpHandlers>
  195. <httpHandlers>
  196.    
  197. </httpHandlers>
  198. </httpHandlers>
  199. </httpHandlers>//
  200. <httpHandlers>
  201. <httpHandlers>
  202. <httpHandlers>
  203.    
  204. </httpHandlers>
  205. </httpHandlers>
  206. </httpHandlers>// 参数:
  207. <httpHandlers>
  208. <httpHandlers>
  209. <httpHandlers>
  210.    
  211. </httpHandlers>
  212. </httpHandlers>
  213. </httpHandlers>//   result:
  214. <httpHandlers>
  215. <httpHandlers>
  216. <httpHandlers>
  217.    
  218. </httpHandlers>
  219. </httpHandlers>
  220. </httpHandlers>//<httpHandlers>
  221. <httpHandlers>
  222. <httpHandlers>
  223.    
  224. </httpHandlers>
  225. </httpHandlers>
  226. </httpHandlers> 包含有关进程状态信息的 System.IAsyncResult。
  227. <httpHandlers>
  228. <httpHandlers>
  229. <httpHandlers>
  230.    
  231. </httpHandlers>
  232. </httpHandlers>
  233. </httpHandlers>void EndProcessRequest(IAsyncResult result);
  234. }
复制代码
IHttpAsyncHandler接口的二个方法该如何使用,可参考我的博客【细说ASP.NET的各种异步操作】,本文也将不再重复讲解。
如果我们创建了一个自定义的HttpHandler,那么为了能让它处理某些HTTP请求,我们还需将它注册到web.config中,就像下面这样:
  1. <httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>
复制代码
虽然我以前的博客中也曾多次涉及到HttpHandler,但感觉还是没有把它完整地说清楚,今天的博客将继续以前的话题,因为我认为HttpHandler实在是太重要了。
HttpHandler的映射过程

在博客【用Asp.net写自己的服务框架】中,我从MSDN中摘选了一些ASP.NET管线事件,在这些事件中,第10个事件【根据所请求资源的文件扩展名(在应用程序的配置文件中映射),选择实现 IHttpHandler 的类,对请求进行处理】就是本文要介绍的重点事件。这个事件也是HttpHandler创建的地方。
由于IIS6,7在管线事件触发机制上的有一定的差别,本文将以ASP.NET 2.0以及IIS6的运行方式来介绍这个过程,IIS7的集成模式下只是触发机制不同,但事件的绝大部分是一样的。管线事件由HttpApplication控制,由MapHandlerExecutionStep负责封装这个事件的执行过程:
  1. internal class MapHandlerExecutionStep : HttpApplication.IExecutionStep{<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>private HttpApplication _application;<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>void HttpApplication.IExecutionStep.Execute()<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers>{<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers><httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>HttpContext context = this._application.Context;<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers><httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers>HttpRequest request = context.Request;<httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers><httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers>//我删除了一些与本文无关的调用代码<httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers><httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers>context.Handler = this._application.MapHttpHandler(<httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers><httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers><httpHandlers>
  80. <httpHandlers>
  81. <httpHandlers>
  82.    
  83. </httpHandlers>
  84. </httpHandlers>
  85. </httpHandlers><httpHandlers>
  86. <httpHandlers>
  87. <httpHandlers>
  88.    
  89. </httpHandlers>
  90. </httpHandlers>
  91. </httpHandlers>context, request.RequestType, request.FilePathObject, request.PhysicalPathInternal, false);<httpHandlers>
  92. <httpHandlers>
  93. <httpHandlers>
  94.    
  95. </httpHandlers>
  96. </httpHandlers>
  97. </httpHandlers>}
复制代码
Execute()最终调用了MapHttpHandler()方法,这个映射过程是由HttpApplication实现的。
MapHttpHandler方法的实现如下:注意代码中我加入的注释。
  1. /// /// 根据虚拟路径映射到具体的HttpHandler对象/// /// HttpContext的实例/// GET, POST .../// 一个虚拟路径映射的字符串: /abc.aspx/// 要请求的物理文件的路径/// /// 具体的HttpHandler对象internal IHttpHandler MapHttpHandler(HttpContext context, string requestType,<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers><httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers><httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers><httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers><httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers><httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers><httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers><httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers><httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers> VirtualPath path, string pathTranslated, bool useAppConfig){<httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers>// 说明:这段代码是我精简后的代码。为了便于理解,我去掉了一些与请求无关的代码行。<httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers>IHttpHandler handler = (context.ServerExecuteDepth == 0) ? context.RemapHandlerInstance : null;<httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers>//用于将当前线程的运行帐号切换为web.config指定的帐号<httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers>using( new ApplicationImpersonationContext() ) {<httpHandlers>
  80. <httpHandlers>
  81. <httpHandlers>
  82.    
  83. </httpHandlers>
  84. </httpHandlers>
  85. </httpHandlers><httpHandlers>
  86. <httpHandlers>
  87. <httpHandlers>
  88.    
  89. </httpHandlers>
  90. </httpHandlers>
  91. </httpHandlers>// 如果之前调用过context.RemapHandler(),则直接返回那个HttpHandler<httpHandlers>
  92. <httpHandlers>
  93. <httpHandlers>
  94.    
  95. </httpHandlers>
  96. </httpHandlers>
  97. </httpHandlers><httpHandlers>
  98. <httpHandlers>
  99. <httpHandlers>
  100.    
  101. </httpHandlers>
  102. </httpHandlers>
  103. </httpHandlers>// 把这个判断放在这里似乎没有意义,应该放在using前面,那样岂不是更快吗?【fish li个人意见】<httpHandlers>
  104. <httpHandlers>
  105. <httpHandlers>
  106.    
  107. </httpHandlers>
  108. </httpHandlers>
  109. </httpHandlers><httpHandlers>
  110. <httpHandlers>
  111. <httpHandlers>
  112.    
  113. </httpHandlers>
  114. </httpHandlers>
  115. </httpHandlers>if( handler != null )<httpHandlers>
  116. <httpHandlers>
  117. <httpHandlers>
  118.    
  119. </httpHandlers>
  120. </httpHandlers>
  121. </httpHandlers><httpHandlers>
  122. <httpHandlers>
  123. <httpHandlers>
  124.    
  125. </httpHandlers>
  126. </httpHandlers>
  127. </httpHandlers><httpHandlers>
  128. <httpHandlers>
  129. <httpHandlers>
  130.    
  131. </httpHandlers>
  132. </httpHandlers>
  133. </httpHandlers>return handler;<httpHandlers>
  134. <httpHandlers>
  135. <httpHandlers>
  136.    
  137. </httpHandlers>
  138. </httpHandlers>
  139. </httpHandlers><httpHandlers>
  140. <httpHandlers>
  141. <httpHandlers>
  142.    
  143. </httpHandlers>
  144. </httpHandlers>
  145. </httpHandlers>// 到  配置中查找一个能与requestType以及path匹配的配置项<httpHandlers>
  146. <httpHandlers>
  147. <httpHandlers>
  148.    
  149. </httpHandlers>
  150. </httpHandlers>
  151. </httpHandlers><httpHandlers>
  152. <httpHandlers>
  153. <httpHandlers>
  154.    
  155. </httpHandlers>
  156. </httpHandlers>
  157. </httpHandlers>HttpHandlerAction mapping = this.GetHandlerMapping(context, requestType, path, useAppConfig);<httpHandlers>
  158. <httpHandlers>
  159. <httpHandlers>
  160.    
  161. </httpHandlers>
  162. </httpHandlers>
  163. </httpHandlers><httpHandlers>
  164. <httpHandlers>
  165. <httpHandlers>
  166.    
  167. </httpHandlers>
  168. </httpHandlers>
  169. </httpHandlers>if( mapping == null )<httpHandlers>
  170. <httpHandlers>
  171. <httpHandlers>
  172.    
  173. </httpHandlers>
  174. </httpHandlers>
  175. </httpHandlers><httpHandlers>
  176. <httpHandlers>
  177. <httpHandlers>
  178.    
  179. </httpHandlers>
  180. </httpHandlers>
  181. </httpHandlers><httpHandlers>
  182. <httpHandlers>
  183. <httpHandlers>
  184.    
  185. </httpHandlers>
  186. </httpHandlers>
  187. </httpHandlers> throw new HttpException("Http_handler_not_found_for_request_type");<httpHandlers>
  188. <httpHandlers>
  189. <httpHandlers>
  190.    
  191. </httpHandlers>
  192. </httpHandlers>
  193. </httpHandlers><httpHandlers>
  194. <httpHandlers>
  195. <httpHandlers>
  196.    
  197. </httpHandlers>
  198. </httpHandlers>
  199. </httpHandlers>// 获取IHttpHandlerFactory对象,这是比较重要的调用。<httpHandlers>
  200. <httpHandlers>
  201. <httpHandlers>
  202.    
  203. </httpHandlers>
  204. </httpHandlers>
  205. </httpHandlers><httpHandlers>
  206. <httpHandlers>
  207. <httpHandlers>
  208.    
  209. </httpHandlers>
  210. </httpHandlers>
  211. </httpHandlers>IHttpHandlerFactory factory = this.GetFactory(mapping);<httpHandlers>
  212. <httpHandlers>
  213. <httpHandlers>
  214.    
  215. </httpHandlers>
  216. </httpHandlers>
  217. </httpHandlers><httpHandlers>
  218. <httpHandlers>
  219. <httpHandlers>
  220.    
  221. </httpHandlers>
  222. </httpHandlers>
  223. </httpHandlers>// 尝试转换成IHttpHandlerFactory2对象。设计二个IHttpHandlerFactory的原因与参数的可见类型有关。<httpHandlers>
  224. <httpHandlers>
  225. <httpHandlers>
  226.    
  227. </httpHandlers>
  228. </httpHandlers>
  229. </httpHandlers><httpHandlers>
  230. <httpHandlers>
  231. <httpHandlers>
  232.    
  233. </httpHandlers>
  234. </httpHandlers>
  235. </httpHandlers>IHttpHandlerFactory2 factory2 = factory as IHttpHandlerFactory2;<httpHandlers>
  236. <httpHandlers>
  237. <httpHandlers>
  238.    
  239. </httpHandlers>
  240. </httpHandlers>
  241. </httpHandlers><httpHandlers>
  242. <httpHandlers>
  243. <httpHandlers>
  244.    
  245. </httpHandlers>
  246. </httpHandlers>
  247. </httpHandlers>// 调用IHttpHandlerFactory对象的GetHandler方法获取具体的HttpHandler对象<httpHandlers>
  248. <httpHandlers>
  249. <httpHandlers>
  250.    
  251. </httpHandlers>
  252. </httpHandlers>
  253. </httpHandlers><httpHandlers>
  254. <httpHandlers>
  255. <httpHandlers>
  256.    
  257. </httpHandlers>
  258. </httpHandlers>
  259. </httpHandlers>if( factory2 != null )<httpHandlers>
  260. <httpHandlers>
  261. <httpHandlers>
  262.    
  263. </httpHandlers>
  264. </httpHandlers>
  265. </httpHandlers><httpHandlers>
  266. <httpHandlers>
  267. <httpHandlers>
  268.    
  269. </httpHandlers>
  270. </httpHandlers>
  271. </httpHandlers><httpHandlers>
  272. <httpHandlers>
  273. <httpHandlers>
  274.    
  275. </httpHandlers>
  276. </httpHandlers>
  277. </httpHandlers> handler = factory2.GetHandler(context, requestType, path, pathTranslated);<httpHandlers>
  278. <httpHandlers>
  279. <httpHandlers>
  280.    
  281. </httpHandlers>
  282. </httpHandlers>
  283. </httpHandlers><httpHandlers>
  284. <httpHandlers>
  285. <httpHandlers>
  286.    
  287. </httpHandlers>
  288. </httpHandlers>
  289. </httpHandlers><httpHandlers>
  290. <httpHandlers>
  291. <httpHandlers>
  292.    
  293. </httpHandlers>
  294. </httpHandlers>
  295. </httpHandlers><httpHandlers>
  296. <httpHandlers>
  297. <httpHandlers>
  298.    
  299. </httpHandlers>
  300. </httpHandlers>
  301. </httpHandlers><httpHandlers>
  302. <httpHandlers>
  303. <httpHandlers>
  304.    
  305. </httpHandlers>
  306. </httpHandlers>
  307. </httpHandlers><httpHandlers>
  308. <httpHandlers>
  309. <httpHandlers>
  310.    
  311. </httpHandlers>
  312. </httpHandlers>
  313. </httpHandlers>else<httpHandlers>
  314. <httpHandlers>
  315. <httpHandlers>
  316.    
  317. </httpHandlers>
  318. </httpHandlers>
  319. </httpHandlers><httpHandlers>
  320. <httpHandlers>
  321. <httpHandlers>
  322.    
  323. </httpHandlers>
  324. </httpHandlers>
  325. </httpHandlers><httpHandlers>
  326. <httpHandlers>
  327. <httpHandlers>
  328.    
  329. </httpHandlers>
  330. </httpHandlers>
  331. </httpHandlers> handler = factory.GetHandler(context, requestType, path.VirtualPathString, pathTranslated);<httpHandlers>
  332. <httpHandlers>
  333. <httpHandlers>
  334.    
  335. </httpHandlers>
  336. </httpHandlers>
  337. </httpHandlers><httpHandlers>
  338. <httpHandlers>
  339. <httpHandlers>
  340.    
  341. </httpHandlers>
  342. </httpHandlers>
  343. </httpHandlers>// 将这二个对象都添加到【临时】回收列表。在管线处理的结尾处,会调用HandlerWithFactory.Recycle()<httpHandlers>
  344. <httpHandlers>
  345. <httpHandlers>
  346.    
  347. </httpHandlers>
  348. </httpHandlers>
  349. </httpHandlers><httpHandlers>
  350. <httpHandlers>
  351. <httpHandlers>
  352.    
  353. </httpHandlers>
  354. </httpHandlers>
  355. </httpHandlers>// 进而会调用factory.ReleaseHandler(),最后会丢掉_handlerRecycleList的引用。<httpHandlers>
  356. <httpHandlers>
  357. <httpHandlers>
  358.    
  359. </httpHandlers>
  360. </httpHandlers>
  361. </httpHandlers><httpHandlers>
  362. <httpHandlers>
  363. <httpHandlers>
  364.    
  365. </httpHandlers>
  366. </httpHandlers>
  367. </httpHandlers>// 因此factory的重用与这里无关,它只可能会影响handler<httpHandlers>
  368. <httpHandlers>
  369. <httpHandlers>
  370.    
  371. </httpHandlers>
  372. </httpHandlers>
  373. </httpHandlers><httpHandlers>
  374. <httpHandlers>
  375. <httpHandlers>
  376.    
  377. </httpHandlers>
  378. </httpHandlers>
  379. </httpHandlers>this._handlerRecycleList.Add(new HandlerWithFactory(handler, factory));<httpHandlers>
  380. <httpHandlers>
  381. <httpHandlers>
  382.    
  383. </httpHandlers>
  384. </httpHandlers>
  385. </httpHandlers>}<httpHandlers>
  386. <httpHandlers>
  387. <httpHandlers>
  388.    
  389. </httpHandlers>
  390. </httpHandlers>
  391. </httpHandlers>return handler;}
复制代码
今天的代码将着重分析这段代码,以揭示HttpHandler的映射过程。
在这段代码中,有3个主要的调用过程:
1. this.GetHandlerMapping(context, requestType, path, useAppConfig)
2. this.GetFactory(mapping)
3. factory.GetHandler(context, requestType, path.VirtualPathString, pathTranslated)
后面将着重分析这三个调用。
HttpContext.RemapHandler()

在MapHttpHandler()方法的开始处,有这么一段代码,不知您注意没有?
  1. IHttpHandler handler = (context.ServerExecuteDepth == 0) ? context.RemapHandlerInstance : null;if( handler != null )<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>return handler;
复制代码
这段代码是什么意思呢?
为了能让您较为简单地理解这段代码的意义,请看我准备的一个示例:
我创建了一个TestRemapHandler.ashx文件:
  1. using System;using System.Web;public class TestRemapHandler : IHttpHandler {<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers><httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>public void ProcessRequest (HttpContext context) {<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers><httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers>context.Response.ContentType = "text/plain";<httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers><httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers>context.Response.Write("Hello TestRemapHandler");<httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers>}<httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers> public bool IsReusable {<httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers><httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers>get {<httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers><httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers><httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers>return false;<httpHandlers>
  80. <httpHandlers>
  81. <httpHandlers>
  82.    
  83. </httpHandlers>
  84. </httpHandlers>
  85. </httpHandlers><httpHandlers>
  86. <httpHandlers>
  87. <httpHandlers>
  88.    
  89. </httpHandlers>
  90. </httpHandlers>
  91. </httpHandlers>}<httpHandlers>
  92. <httpHandlers>
  93. <httpHandlers>
  94.    
  95. </httpHandlers>
  96. </httpHandlers>
  97. </httpHandlers>}}
复制代码
至于这个文件在运行时能输出什么,我想我就不用截图了。
接下来,我再创建一个Global.asax文件,并写了一个事件处理方法:
  1. //protected void Application_PostResolveRequestCache(object sender, EventArgs e)//{//<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>HttpApplication app = (HttpApplication)sender;//<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>if( app.Request.FilePath.EndsWith(".ashx", StringComparison.OrdinalIgnoreCase) )//<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers><httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers>app.Context.RemapHandler(new MyTestHandler());//}// 或者是下面这样protected void Application_PostResolveRequestCache(object sender, EventArgs e){<httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>HttpApplication app = (HttpApplication)sender;<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers>if( app.Request.FilePath.EndsWith("/TestRemapHandler.ashx", StringComparison.OrdinalIgnoreCase) )<httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers><httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers>app.Context.RemapHandler(new MyTestHandler());}
复制代码
MyTestHandler是我定义的一个自定义的HttpHandler,后面的示例也会用到它,所以,我现在就将它的实现代码贴出来:
  1. public class MyTestHandler : IHttpHandler{<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>private Counter _counter = new Counter();<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>public bool IsReusable<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers>{<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers><httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>get { return true; }<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers>}<httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers>public void ProcessRequest(HttpContext context)<httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers>{<httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers><httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers>_counter.ShowCountAndRequestInfo(context);<httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers>}}
复制代码
类型Counter是一个简单的计数器,它的实现如下:
  1. /// /// 一个简单的计数器/// public class Counter{<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>private int _count;<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>public void ShowCountAndRequestInfo(HttpContext context)<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers>{<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers><httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>_count++;<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers><httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers>context.Response.ContentType = "text/plain";<httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers><httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers>context.Response.Write("count: " + _count.ToString());<httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers><httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers>context.Response.Write("\r\n");<httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers><httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers>context.Response.Write(context.Request.RawUrl);<httpHandlers>
  80. <httpHandlers>
  81. <httpHandlers>
  82.    
  83. </httpHandlers>
  84. </httpHandlers>
  85. </httpHandlers>}}
复制代码
现在,您可以想像一下当我再次访问TestRemapHandler.ashx时,会在浏览器中看到什么?


以下是我看到的结果:
1.png

从截图中,我们可以看出,服务端的输出并不是TestRemapHandler.ashx产生的,而是由MyTestHandler产生的。这也说明我调用Context.RemapHandler()确实影响了后面的MapHttpHandler过程。现在我们再回过头来再看一下前面那段代码:
  1. IHttpHandler handler = (context.ServerExecuteDepth == 0) ? context.RemapHandlerInstance : null;if( handler != null )<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>return handler;
复制代码
这段代码也主要是为配合HttpContext.RemapHandler()一起工作的。这里要补充的是:context.ServerExecuteDepth的判断是说有没有调用HttpServerUtility.Execute()
小结:如果我们在MapHttpHandler事件前调用HttpContext.RemapHandler(),将会直接影响后面的映射过程,或者说,我们可以直接指定一个HttpHandler,而不是让ASP.NET来替我们来决定。
HttpContext.RemapHandler()的另类用途

我在【用Asp.net写自己的服务框架】曾演示过ASP.NET URL路由的设计思路,虽然那个示例能较好地反映微软的Routing组件的工作方式,但对于示例来说,有些代码还是可以简化的。今天我将使用HttpContext.RemapHandler()来简化那段代码,简化后的版本如下:
  1. internal class MyServiceUrlRoutingModule2 : IHttpModule{<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>public void Init(HttpApplication app)<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>{<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers><httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers>app.PostResolveRequestCache += new EventHandler(app_PostResolveRequestCache);<httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>}<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers>private void app_PostResolveRequestCache(object sender, EventArgs e)<httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers>{<httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers><httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers>HttpApplication app = (HttpApplication)sender;<httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers><httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers>// 根据HttpContext,获取合适的HttpHandler,这个过程俗称路由<httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers><httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers>// 通常就是根据URL去主动寻找一个合适的HttpHandler<httpHandlers>
  80. <httpHandlers>
  81. <httpHandlers>
  82.    
  83. </httpHandlers>
  84. </httpHandlers>
  85. </httpHandlers><httpHandlers>
  86. <httpHandlers>
  87. <httpHandlers>
  88.    
  89. </httpHandlers>
  90. </httpHandlers>
  91. </httpHandlers>// 查找过程仍使用上一版的方法<httpHandlers>
  92. <httpHandlers>
  93. <httpHandlers>
  94.    
  95. </httpHandlers>
  96. </httpHandlers>
  97. </httpHandlers><httpHandlers>
  98. <httpHandlers>
  99. <httpHandlers>
  100.    
  101. </httpHandlers>
  102. </httpHandlers>
  103. </httpHandlers>MyServiceHandler handler = MyServiceUrlRoutingModule.GetHandler(app.Context);<httpHandlers>
  104. <httpHandlers>
  105. <httpHandlers>
  106.    
  107. </httpHandlers>
  108. </httpHandlers>
  109. </httpHandlers><httpHandlers>
  110. <httpHandlers>
  111. <httpHandlers>
  112.    
  113. </httpHandlers>
  114. </httpHandlers>
  115. </httpHandlers>if( handler != null )<httpHandlers>
  116. <httpHandlers>
  117. <httpHandlers>
  118.    
  119. </httpHandlers>
  120. </httpHandlers>
  121. </httpHandlers><httpHandlers>
  122. <httpHandlers>
  123. <httpHandlers>
  124.    
  125. </httpHandlers>
  126. </httpHandlers>
  127. </httpHandlers><httpHandlers>
  128. <httpHandlers>
  129. <httpHandlers>
  130.    
  131. </httpHandlers>
  132. </httpHandlers>
  133. </httpHandlers>// 直接设置已找到的HttpHandler<httpHandlers>
  134. <httpHandlers>
  135. <httpHandlers>
  136.    
  137. </httpHandlers>
  138. </httpHandlers>
  139. </httpHandlers><httpHandlers>
  140. <httpHandlers>
  141. <httpHandlers>
  142.    
  143. </httpHandlers>
  144. </httpHandlers>
  145. </httpHandlers><httpHandlers>
  146. <httpHandlers>
  147. <httpHandlers>
  148.    
  149. </httpHandlers>
  150. </httpHandlers>
  151. </httpHandlers>app.Context.RemapHandler(handler);<httpHandlers>
  152. <httpHandlers>
  153. <httpHandlers>
  154.    
  155. </httpHandlers>
  156. </httpHandlers>
  157. </httpHandlers>}<httpHandlers>
  158. <httpHandlers>
  159. <httpHandlers>
  160.    
  161. </httpHandlers>
  162. </httpHandlers>
  163. </httpHandlers>public void Dispose()<httpHandlers>
  164. <httpHandlers>
  165. <httpHandlers>
  166.    
  167. </httpHandlers>
  168. </httpHandlers>
  169. </httpHandlers>{<httpHandlers>
  170. <httpHandlers>
  171. <httpHandlers>
  172.    
  173. </httpHandlers>
  174. </httpHandlers>
  175. </httpHandlers>}}
复制代码
在MyServiceUrlRoutingModule2这个新版本中,基本上跳过了MapHttpHandler()中所有复杂的处理逻辑,因此会更快。
这种方法虽然更简单,但它只能设置一个参数IHttpHandler,因此,如果有其它的参数需要一起传递,则要修改相关的HttpHandler类型,以便容纳需要传递的参数。例如,在【我的服务框架】中,MyServiceHandler类型就专门定义了一个属性ServiceInfo来保存要调用的方法信息。MyServiceUrlRoutingModule.GetHandler()的实现代码如下:
  1. internal static MyServiceHandler GetHandler(HttpContext context){<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>NamesPair pair = FrameworkRules.ParseNamesPair(context.Request);<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>if( pair == null )<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers><httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers>return null;<httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>InvokeInfo vkInfo = ReflectionHelper.GetInvokeInfo(pair);<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers>if( vkInfo == null )<httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers><httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers>ExceptionHelper.Throw404Exception(context);<httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers>MyServiceHandler handler = MyServiceHandlerFactory.GetHandler(vkInfo);<httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers>handler.ServiceInfo = new ServiceInfo(pair, vkInfo);<httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers>return handler;}
复制代码
写到这里,有个问题把我难住了:为什么ASP.NET 3.5 UrlRoutingModule不用RemapHandler()而是采用较复杂的方法呢?难道是为了能保留二个参数吗?但那个【context.Request.Path】没有必要保存呢。实在是没有想通,最后想到ASP.NET 4.0 UrlRoutingModule会不会不一样了?于是,只好再次安装 .net framework 4.0 了(没办法,老家的旧机器上还真没有.net 4.0),结果当我用Reflector.exe找到4.0版本的UrlRoutingModule时,发现它已被移到System.Web.dll中,而且,ASPL.NET 4.0也在使用RemapHandler() ! 看来微软当初忘记了这个方法。
GetHandlerMapping()

在MapHttpHandler()方法中,有下面这个调用:
  1. // 到 <httpHandlers> 配置中查找一个能与requestType以及path匹配的配置项
  2. HttpHandlerAction mapping = this.GetHandlerMapping(context, requestType, path, useAppConfig);
复制代码
接下来,我们再来看一下这个调用的实现代码:
  1. private HttpHandlerAction GetHandlerMapping(HttpContext context, string requestType, VirtualPath path, bool useAppConfig){<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>CachedPathData pathData = null;<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>HandlerMappingMemo cachedHandler = null;<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers>HttpHandlerAction mapping = null;<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers>if (!useAppConfig)<httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>{<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers><httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers>// 先从缓存中查找<httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers><httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers>pathData = context.GetPathData(path);<httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers><httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers>cachedHandler = pathData.CachedHandler;<httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers><httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers>if ((cachedHandler != null) && !cachedHandler.IsMatch(requestType, path))<httpHandlers>
  80. <httpHandlers>
  81. <httpHandlers>
  82.    
  83. </httpHandlers>
  84. </httpHandlers>
  85. </httpHandlers><httpHandlers>
  86. <httpHandlers>
  87. <httpHandlers>
  88.    
  89. </httpHandlers>
  90. </httpHandlers>
  91. </httpHandlers>{<httpHandlers>
  92. <httpHandlers>
  93. <httpHandlers>
  94.    
  95. </httpHandlers>
  96. </httpHandlers>
  97. </httpHandlers><httpHandlers>
  98. <httpHandlers>
  99. <httpHandlers>
  100.    
  101. </httpHandlers>
  102. </httpHandlers>
  103. </httpHandlers><httpHandlers>
  104. <httpHandlers>
  105. <httpHandlers>
  106.    
  107. </httpHandlers>
  108. </httpHandlers>
  109. </httpHandlers>cachedHandler = null;<httpHandlers>
  110. <httpHandlers>
  111. <httpHandlers>
  112.    
  113. </httpHandlers>
  114. </httpHandlers>
  115. </httpHandlers><httpHandlers>
  116. <httpHandlers>
  117. <httpHandlers>
  118.    
  119. </httpHandlers>
  120. </httpHandlers>
  121. </httpHandlers>}<httpHandlers>
  122. <httpHandlers>
  123. <httpHandlers>
  124.    
  125. </httpHandlers>
  126. </httpHandlers>
  127. </httpHandlers>}<httpHandlers>
  128. <httpHandlers>
  129. <httpHandlers>
  130.    
  131. </httpHandlers>
  132. </httpHandlers>
  133. </httpHandlers>if (cachedHandler == null)<httpHandlers>
  134. <httpHandlers>
  135. <httpHandlers>
  136.    
  137. </httpHandlers>
  138. </httpHandlers>
  139. </httpHandlers>{<httpHandlers>
  140. <httpHandlers>
  141. <httpHandlers>
  142.    
  143. </httpHandlers>
  144. </httpHandlers>
  145. </httpHandlers><httpHandlers>
  146. <httpHandlers>
  147. <httpHandlers>
  148.    
  149. </httpHandlers>
  150. </httpHandlers>
  151. </httpHandlers>// 根据配置文件,查找映射<httpHandlers>
  152. <httpHandlers>
  153. <httpHandlers>
  154.    
  155. </httpHandlers>
  156. </httpHandlers>
  157. </httpHandlers><httpHandlers>
  158. <httpHandlers>
  159. <httpHandlers>
  160.    
  161. </httpHandlers>
  162. </httpHandlers>
  163. </httpHandlers>mapping = (useAppConfig ? RuntimeConfig.GetAppConfig().HttpHandlers<httpHandlers>
  164. <httpHandlers>
  165. <httpHandlers>
  166.    
  167. </httpHandlers>
  168. </httpHandlers>
  169. </httpHandlers><httpHandlers>
  170. <httpHandlers>
  171. <httpHandlers>
  172.    
  173. </httpHandlers>
  174. </httpHandlers>
  175. </httpHandlers><httpHandlers>
  176. <httpHandlers>
  177. <httpHandlers>
  178.    
  179. </httpHandlers>
  180. </httpHandlers>
  181. </httpHandlers><httpHandlers>
  182. <httpHandlers>
  183. <httpHandlers>
  184.    
  185. </httpHandlers>
  186. </httpHandlers>
  187. </httpHandlers><httpHandlers>
  188. <httpHandlers>
  189. <httpHandlers>
  190.    
  191. </httpHandlers>
  192. </httpHandlers>
  193. </httpHandlers><httpHandlers>
  194. <httpHandlers>
  195. <httpHandlers>
  196.    
  197. </httpHandlers>
  198. </httpHandlers>
  199. </httpHandlers><httpHandlers>
  200. <httpHandlers>
  201. <httpHandlers>
  202.    
  203. </httpHandlers>
  204. </httpHandlers>
  205. </httpHandlers><httpHandlers>
  206. <httpHandlers>
  207. <httpHandlers>
  208.    
  209. </httpHandlers>
  210. </httpHandlers>
  211. </httpHandlers> : RuntimeConfig.GetConfig(context).HttpHandlers)<httpHandlers>
  212. <httpHandlers>
  213. <httpHandlers>
  214.    
  215. </httpHandlers>
  216. </httpHandlers>
  217. </httpHandlers><httpHandlers>
  218. <httpHandlers>
  219. <httpHandlers>
  220.    
  221. </httpHandlers>
  222. </httpHandlers>
  223. </httpHandlers><httpHandlers>
  224. <httpHandlers>
  225. <httpHandlers>
  226.    
  227. </httpHandlers>
  228. </httpHandlers>
  229. </httpHandlers>.FindMapping(requestType, path);<httpHandlers>
  230. <httpHandlers>
  231. <httpHandlers>
  232.    
  233. </httpHandlers>
  234. </httpHandlers>
  235. </httpHandlers><httpHandlers>
  236. <httpHandlers>
  237. <httpHandlers>
  238.    
  239. </httpHandlers>
  240. </httpHandlers>
  241. </httpHandlers>if (!useAppConfig)<httpHandlers>
  242. <httpHandlers>
  243. <httpHandlers>
  244.    
  245. </httpHandlers>
  246. </httpHandlers>
  247. </httpHandlers><httpHandlers>
  248. <httpHandlers>
  249. <httpHandlers>
  250.    
  251. </httpHandlers>
  252. </httpHandlers>
  253. </httpHandlers>{<httpHandlers>
  254. <httpHandlers>
  255. <httpHandlers>
  256.    
  257. </httpHandlers>
  258. </httpHandlers>
  259. </httpHandlers><httpHandlers>
  260. <httpHandlers>
  261. <httpHandlers>
  262.    
  263. </httpHandlers>
  264. </httpHandlers>
  265. </httpHandlers><httpHandlers>
  266. <httpHandlers>
  267. <httpHandlers>
  268.    
  269. </httpHandlers>
  270. </httpHandlers>
  271. </httpHandlers>// 将查找到的结果放入缓存<httpHandlers>
  272. <httpHandlers>
  273. <httpHandlers>
  274.    
  275. </httpHandlers>
  276. </httpHandlers>
  277. </httpHandlers><httpHandlers>
  278. <httpHandlers>
  279. <httpHandlers>
  280.    
  281. </httpHandlers>
  282. </httpHandlers>
  283. </httpHandlers><httpHandlers>
  284. <httpHandlers>
  285. <httpHandlers>
  286.    
  287. </httpHandlers>
  288. </httpHandlers>
  289. </httpHandlers>cachedHandler = new HandlerMappingMemo(mapping, requestType, path);<httpHandlers>
  290. <httpHandlers>
  291. <httpHandlers>
  292.    
  293. </httpHandlers>
  294. </httpHandlers>
  295. </httpHandlers><httpHandlers>
  296. <httpHandlers>
  297. <httpHandlers>
  298.    
  299. </httpHandlers>
  300. </httpHandlers>
  301. </httpHandlers><httpHandlers>
  302. <httpHandlers>
  303. <httpHandlers>
  304.    
  305. </httpHandlers>
  306. </httpHandlers>
  307. </httpHandlers>pathData.CachedHandler = cachedHandler;<httpHandlers>
  308. <httpHandlers>
  309. <httpHandlers>
  310.    
  311. </httpHandlers>
  312. </httpHandlers>
  313. </httpHandlers><httpHandlers>
  314. <httpHandlers>
  315. <httpHandlers>
  316.    
  317. </httpHandlers>
  318. </httpHandlers>
  319. </httpHandlers>}<httpHandlers>
  320. <httpHandlers>
  321. <httpHandlers>
  322.    
  323. </httpHandlers>
  324. </httpHandlers>
  325. </httpHandlers><httpHandlers>
  326. <httpHandlers>
  327. <httpHandlers>
  328.    
  329. </httpHandlers>
  330. </httpHandlers>
  331. </httpHandlers>return mapping;<httpHandlers>
  332. <httpHandlers>
  333. <httpHandlers>
  334.    
  335. </httpHandlers>
  336. </httpHandlers>
  337. </httpHandlers>}<httpHandlers>
  338. <httpHandlers>
  339. <httpHandlers>
  340.    
  341. </httpHandlers>
  342. </httpHandlers>
  343. </httpHandlers>return cachedHandler.Mapping;}
复制代码
代码中的重要阶段,我加了一点注释。我们尤其要注意的FindMapping(requestType, path)的那个调用。
但前面的那个RuntimeConfig.GetAppConfig().HttpHandlers 和RuntimeConfig.GetConfig(context).HttpHandlers)又可以得到什么结果呢?
为了能让您更容易地理解这个调用,我准备了一段代码,可以直观地显示这个调用结果:
  1. public partial class TestRuntimeConfig : System.Web.UI.Page{<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>protected string HttpHandlers;<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>protected void Page_Load(object sender, EventArgs e)<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers>{<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers><httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>string typeName = typeof(HttpRequest).AssemblyQualifiedName<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers><httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers><httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers><httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers><httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers><httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers><httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers><httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers><httpHandlers>
  80. <httpHandlers>
  81. <httpHandlers>
  82.    
  83. </httpHandlers>
  84. </httpHandlers>
  85. </httpHandlers><httpHandlers>
  86. <httpHandlers>
  87. <httpHandlers>
  88.    
  89. </httpHandlers>
  90. </httpHandlers>
  91. </httpHandlers>.Replace("HttpRequest", "Configuration.RuntimeConfig");<httpHandlers>
  92. <httpHandlers>
  93. <httpHandlers>
  94.    
  95. </httpHandlers>
  96. </httpHandlers>
  97. </httpHandlers><httpHandlers>
  98. <httpHandlers>
  99. <httpHandlers>
  100.    
  101. </httpHandlers>
  102. </httpHandlers>
  103. </httpHandlers>Type type = Type.GetType(typeName);<httpHandlers>
  104. <httpHandlers>
  105. <httpHandlers>
  106.    
  107. </httpHandlers>
  108. </httpHandlers>
  109. </httpHandlers><httpHandlers>
  110. <httpHandlers>
  111. <httpHandlers>
  112.    
  113. </httpHandlers>
  114. </httpHandlers>
  115. </httpHandlers>bool useAppConfig = Request.QueryString["useAppConfig"] == "1";<httpHandlers>
  116. <httpHandlers>
  117. <httpHandlers>
  118.    
  119. </httpHandlers>
  120. </httpHandlers>
  121. </httpHandlers><httpHandlers>
  122. <httpHandlers>
  123. <httpHandlers>
  124.    
  125. </httpHandlers>
  126. </httpHandlers>
  127. </httpHandlers>// 由于RuntimeConfig类型的可见性是internal,<httpHandlers>
  128. <httpHandlers>
  129. <httpHandlers>
  130.    
  131. </httpHandlers>
  132. </httpHandlers>
  133. </httpHandlers><httpHandlers>
  134. <httpHandlers>
  135. <httpHandlers>
  136.    
  137. </httpHandlers>
  138. </httpHandlers>
  139. </httpHandlers>// 所以,我不能直接用它声明变量,只能使用object类型<httpHandlers>
  140. <httpHandlers>
  141. <httpHandlers>
  142.    
  143. </httpHandlers>
  144. </httpHandlers>
  145. </httpHandlers><httpHandlers>
  146. <httpHandlers>
  147. <httpHandlers>
  148.    
  149. </httpHandlers>
  150. </httpHandlers>
  151. </httpHandlers>object config = null;<httpHandlers>
  152. <httpHandlers>
  153. <httpHandlers>
  154.    
  155. </httpHandlers>
  156. </httpHandlers>
  157. </httpHandlers><httpHandlers>
  158. <httpHandlers>
  159. <httpHandlers>
  160.    
  161. </httpHandlers>
  162. </httpHandlers>
  163. </httpHandlers>if( useAppConfig )<httpHandlers>
  164. <httpHandlers>
  165. <httpHandlers>
  166.    
  167. </httpHandlers>
  168. </httpHandlers>
  169. </httpHandlers><httpHandlers>
  170. <httpHandlers>
  171. <httpHandlers>
  172.    
  173. </httpHandlers>
  174. </httpHandlers>
  175. </httpHandlers><httpHandlers>
  176. <httpHandlers>
  177. <httpHandlers>
  178.    
  179. </httpHandlers>
  180. </httpHandlers>
  181. </httpHandlers>config = type.InvokeMember("GetAppConfig",<httpHandlers>
  182. <httpHandlers>
  183. <httpHandlers>
  184.    
  185. </httpHandlers>
  186. </httpHandlers>
  187. </httpHandlers><httpHandlers>
  188. <httpHandlers>
  189. <httpHandlers>
  190.    
  191. </httpHandlers>
  192. </httpHandlers>
  193. </httpHandlers><httpHandlers>
  194. <httpHandlers>
  195. <httpHandlers>
  196.    
  197. </httpHandlers>
  198. </httpHandlers>
  199. </httpHandlers><httpHandlers>
  200. <httpHandlers>
  201. <httpHandlers>
  202.    
  203. </httpHandlers>
  204. </httpHandlers>
  205. </httpHandlers>BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic,<httpHandlers>
  206. <httpHandlers>
  207. <httpHandlers>
  208.    
  209. </httpHandlers>
  210. </httpHandlers>
  211. </httpHandlers><httpHandlers>
  212. <httpHandlers>
  213. <httpHandlers>
  214.    
  215. </httpHandlers>
  216. </httpHandlers>
  217. </httpHandlers><httpHandlers>
  218. <httpHandlers>
  219. <httpHandlers>
  220.    
  221. </httpHandlers>
  222. </httpHandlers>
  223. </httpHandlers><httpHandlers>
  224. <httpHandlers>
  225. <httpHandlers>
  226.    
  227. </httpHandlers>
  228. </httpHandlers>
  229. </httpHandlers>null, null, null);<httpHandlers>
  230. <httpHandlers>
  231. <httpHandlers>
  232.    
  233. </httpHandlers>
  234. </httpHandlers>
  235. </httpHandlers><httpHandlers>
  236. <httpHandlers>
  237. <httpHandlers>
  238.    
  239. </httpHandlers>
  240. </httpHandlers>
  241. </httpHandlers>else<httpHandlers>
  242. <httpHandlers>
  243. <httpHandlers>
  244.    
  245. </httpHandlers>
  246. </httpHandlers>
  247. </httpHandlers><httpHandlers>
  248. <httpHandlers>
  249. <httpHandlers>
  250.    
  251. </httpHandlers>
  252. </httpHandlers>
  253. </httpHandlers><httpHandlers>
  254. <httpHandlers>
  255. <httpHandlers>
  256.    
  257. </httpHandlers>
  258. </httpHandlers>
  259. </httpHandlers>config = type.InvokeMember("GetConfig",<httpHandlers>
  260. <httpHandlers>
  261. <httpHandlers>
  262.    
  263. </httpHandlers>
  264. </httpHandlers>
  265. </httpHandlers><httpHandlers>
  266. <httpHandlers>
  267. <httpHandlers>
  268.    
  269. </httpHandlers>
  270. </httpHandlers>
  271. </httpHandlers><httpHandlers>
  272. <httpHandlers>
  273. <httpHandlers>
  274.    
  275. </httpHandlers>
  276. </httpHandlers>
  277. </httpHandlers><httpHandlers>
  278. <httpHandlers>
  279. <httpHandlers>
  280.    
  281. </httpHandlers>
  282. </httpHandlers>
  283. </httpHandlers>BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic,<httpHandlers>
  284. <httpHandlers>
  285. <httpHandlers>
  286.    
  287. </httpHandlers>
  288. </httpHandlers>
  289. </httpHandlers><httpHandlers>
  290. <httpHandlers>
  291. <httpHandlers>
  292.    
  293. </httpHandlers>
  294. </httpHandlers>
  295. </httpHandlers><httpHandlers>
  296. <httpHandlers>
  297. <httpHandlers>
  298.    
  299. </httpHandlers>
  300. </httpHandlers>
  301. </httpHandlers><httpHandlers>
  302. <httpHandlers>
  303. <httpHandlers>
  304.    
  305. </httpHandlers>
  306. </httpHandlers>
  307. </httpHandlers>null, null, new object[] { this.Context });<httpHandlers>
  308. <httpHandlers>
  309. <httpHandlers>
  310.    
  311. </httpHandlers>
  312. </httpHandlers>
  313. </httpHandlers><httpHandlers>
  314. <httpHandlers>
  315. <httpHandlers>
  316.    
  317. </httpHandlers>
  318. </httpHandlers>
  319. </httpHandlers>HttpHandlersSection section = (HttpHandlersSection)type.InvokeMember("HttpHandlers",<httpHandlers>
  320. <httpHandlers>
  321. <httpHandlers>
  322.    
  323. </httpHandlers>
  324. </httpHandlers>
  325. </httpHandlers><httpHandlers>
  326. <httpHandlers>
  327. <httpHandlers>
  328.    
  329. </httpHandlers>
  330. </httpHandlers>
  331. </httpHandlers><httpHandlers>
  332. <httpHandlers>
  333. <httpHandlers>
  334.    
  335. </httpHandlers>
  336. </httpHandlers>
  337. </httpHandlers> BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,<httpHandlers>
  338. <httpHandlers>
  339. <httpHandlers>
  340.    
  341. </httpHandlers>
  342. </httpHandlers>
  343. </httpHandlers><httpHandlers>
  344. <httpHandlers>
  345. <httpHandlers>
  346.    
  347. </httpHandlers>
  348. </httpHandlers>
  349. </httpHandlers><httpHandlers>
  350. <httpHandlers>
  351. <httpHandlers>
  352.    
  353. </httpHandlers>
  354. </httpHandlers>
  355. </httpHandlers> null, config, null);<httpHandlers>
  356. <httpHandlers>
  357. <httpHandlers>
  358.    
  359. </httpHandlers>
  360. </httpHandlers>
  361. </httpHandlers><httpHandlers>
  362. <httpHandlers>
  363. <httpHandlers>
  364.    
  365. </httpHandlers>
  366. </httpHandlers>
  367. </httpHandlers>HttpHandlers = string.Format("总共 {0} 个配置项。
  368. ", section.Handlers.Count) +<httpHandlers>
  369. <httpHandlers>
  370. <httpHandlers>
  371.    
  372. </httpHandlers>
  373. </httpHandlers>
  374. </httpHandlers><httpHandlers>
  375. <httpHandlers>
  376. <httpHandlers>
  377.    
  378. </httpHandlers>
  379. </httpHandlers>
  380. </httpHandlers><httpHandlers>
  381. <httpHandlers>
  382. <httpHandlers>
  383.    
  384. </httpHandlers>
  385. </httpHandlers>
  386. </httpHandlers>string.Join("
  387. ", (<httpHandlers>
  388. <httpHandlers>
  389. <httpHandlers>
  390.    
  391. </httpHandlers>
  392. </httpHandlers>
  393. </httpHandlers><httpHandlers>
  394. <httpHandlers>
  395. <httpHandlers>
  396.    
  397. </httpHandlers>
  398. </httpHandlers>
  399. </httpHandlers><httpHandlers>
  400. <httpHandlers>
  401. <httpHandlers>
  402.    
  403. </httpHandlers>
  404. </httpHandlers>
  405. </httpHandlers><httpHandlers>
  406. <httpHandlers>
  407. <httpHandlers>
  408.    
  409. </httpHandlers>
  410. </httpHandlers>
  411. </httpHandlers>from h in section.Handlers.Cast()<httpHandlers>
  412. <httpHandlers>
  413. <httpHandlers>
  414.    
  415. </httpHandlers>
  416. </httpHandlers>
  417. </httpHandlers><httpHandlers>
  418. <httpHandlers>
  419. <httpHandlers>
  420.    
  421. </httpHandlers>
  422. </httpHandlers>
  423. </httpHandlers><httpHandlers>
  424. <httpHandlers>
  425. <httpHandlers>
  426.    
  427. </httpHandlers>
  428. </httpHandlers>
  429. </httpHandlers><httpHandlers>
  430. <httpHandlers>
  431. <httpHandlers>
  432.    
  433. </httpHandlers>
  434. </httpHandlers>
  435. </httpHandlers>let action = string.Format("path="{0}" verb="{1}" validate="{2}" type="{3}"",<httpHandlers>
  436. <httpHandlers>
  437. <httpHandlers>
  438.    
  439. </httpHandlers>
  440. </httpHandlers>
  441. </httpHandlers><httpHandlers>
  442. <httpHandlers>
  443. <httpHandlers>
  444.    
  445. </httpHandlers>
  446. </httpHandlers>
  447. </httpHandlers><httpHandlers>
  448. <httpHandlers>
  449. <httpHandlers>
  450.    
  451. </httpHandlers>
  452. </httpHandlers>
  453. </httpHandlers><httpHandlers>
  454. <httpHandlers>
  455. <httpHandlers>
  456.    
  457. </httpHandlers>
  458. </httpHandlers>
  459. </httpHandlers><httpHandlers>
  460. <httpHandlers>
  461. <httpHandlers>
  462.    
  463. </httpHandlers>
  464. </httpHandlers>
  465. </httpHandlers><httpHandlers>
  466. <httpHandlers>
  467. <httpHandlers>
  468.    
  469. </httpHandlers>
  470. </httpHandlers>
  471. </httpHandlers>h.Path, h.Verb, h.Validate, h.Type)<httpHandlers>
  472. <httpHandlers>
  473. <httpHandlers>
  474.    
  475. </httpHandlers>
  476. </httpHandlers>
  477. </httpHandlers><httpHandlers>
  478. <httpHandlers>
  479. <httpHandlers>
  480.    
  481. </httpHandlers>
  482. </httpHandlers>
  483. </httpHandlers><httpHandlers>
  484. <httpHandlers>
  485. <httpHandlers>
  486.    
  487. </httpHandlers>
  488. </httpHandlers>
  489. </httpHandlers><httpHandlers>
  490. <httpHandlers>
  491. <httpHandlers>
  492.    
  493. </httpHandlers>
  494. </httpHandlers>
  495. </httpHandlers>select action).ToArray());<httpHandlers>
  496. <httpHandlers>
  497. <httpHandlers>
  498.    
  499. </httpHandlers>
  500. </httpHandlers>
  501. </httpHandlers>}}
复制代码
我的示例网站中的web.config中的配置节定义如下:
  1. <httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers><httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>
复制代码
那么,前面的示例代码的运行结果如下:
2.png

通过前面分析可知,代码中的HttpHandlers实际就是在运行时所能访问到的配置集合。而且,我们在网站中所指定的配置会放在集合的前面,ASP.NET的默认配置会在靠后的位置。接下来的FindMapping(requestType, path)的实现如下:
  1. internal HttpHandlerAction FindMapping(string verb, VirtualPath path){<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>this.ValidateHandlers();<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>for (int i = 0; i < this.Handlers.Count; i++)<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers>{<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers><httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>HttpHandlerAction action = this.Handlers[i];<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers><httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers>if (action.IsMatch(verb, path))<httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers><httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers>{<httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers><httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers><httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers>return action;<httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers><httpHandlers>
  80. <httpHandlers>
  81. <httpHandlers>
  82.    
  83. </httpHandlers>
  84. </httpHandlers>
  85. </httpHandlers>}<httpHandlers>
  86. <httpHandlers>
  87. <httpHandlers>
  88.    
  89. </httpHandlers>
  90. </httpHandlers>
  91. </httpHandlers>}<httpHandlers>
  92. <httpHandlers>
  93. <httpHandlers>
  94.    
  95. </httpHandlers>
  96. </httpHandlers>
  97. </httpHandlers>return null;}
复制代码
从代码可以看出,其实所谓的【查找】过程,也就是【逐一匹配】每个在定义的配置项。
至于action.IsMatch()的匹配方式,我们可以从调用所传递的参数看出,其实只是判断【verb, path】这二个参数而已。这个匹配过程的实现代码较长,我就不贴出它们的实现代码了,而是打算通过示例来说明它是如何匹配的。
action.IsMatch()的匹配方式也可以算是GetHandlerMapping()的核心过程。而这里的action的类型其实是HttpHandlerAction,它与配置项一一对应。我们可以先来看一下MSDN是如何解释这个配置项的:
3.png

从MSDN的解释中可以看出:verb,path都可以支持【通配符(*)】,并且可以使用逗号(,)来分隔多个预期项。ASP.NET在实现通配符时,内部使用正则表达式的方式,具体过程可以自己去阅读相关代码。
下面,我将通过一个具体的配置项来分析这些配置参数:
  1. [/code]1. path="Ajax*.*.aspx,Ajax*/*.aspx":表示可以接受【Ajax*.*.aspx】或者【Ajax*/*.aspx】这样的URL格式。
  2. 2. verb="*": 表示可以接受所有的HTTP调用,如:GET,POST 等等。
  3. 3. type="MySimpleServiceFramework.AjaxServiceHandler, MySimpleServiceFramework": 表示当某个请求匹配path,verb时,交给MySimpleServiceFramework程序集中的MySimpleServiceFramework.AjaxServiceHandler来处理请求。
  4. 4. validate="true":表示在第一次读取时,验证type的设置是否有效。如果此项设为false,则表示延迟验证(创建时)。默认值:true
  5. 对于这4个属性,有2个比较重要:
  6. 1. type:  type中的字符串必须能在运行时找到一个可创建的类型,且该类型必须实现IHttpHandler或者IHttpHandlerFactory接口。
  7. 2. path:  在很多资料以及技术书籍中,一般都设置为[b]某类文件扩展名[/b],如:*.xxx ,事实上,我们完全可以设置为一个URL模式,而且还可以设置多个URL模式。比如上面的配置示例中的path参数,具体在使用时,可以响应来自客户端的以下请求:
  8. [code]$(function(){<httpHandlers>
  9. <httpHandlers>
  10. <httpHandlers>
  11.    
  12. </httpHandlers>
  13. </httpHandlers>
  14. </httpHandlers>$("#btnSubmit").click( function(){<httpHandlers>
  15. <httpHandlers>
  16. <httpHandlers>
  17.    
  18. </httpHandlers>
  19. </httpHandlers>
  20. </httpHandlers><httpHandlers>
  21. <httpHandlers>
  22. <httpHandlers>
  23.    
  24. </httpHandlers>
  25. </httpHandlers>
  26. </httpHandlers>$.ajax({<httpHandlers>
  27. <httpHandlers>
  28. <httpHandlers>
  29.    
  30. </httpHandlers>
  31. </httpHandlers>
  32. </httpHandlers><httpHandlers>
  33. <httpHandlers>
  34. <httpHandlers>
  35.    
  36. </httpHandlers>
  37. </httpHandlers>
  38. </httpHandlers><httpHandlers>
  39. <httpHandlers>
  40. <httpHandlers>
  41.    
  42. </httpHandlers>
  43. </httpHandlers>
  44. </httpHandlers><httpHandlers>
  45. <httpHandlers>
  46. <httpHandlers>
  47.    
  48. </httpHandlers>
  49. </httpHandlers>
  50. </httpHandlers>// 注意:下面的二个url地址都是可以使用的。<httpHandlers>
  51. <httpHandlers>
  52. <httpHandlers>
  53.    
  54. </httpHandlers>
  55. </httpHandlers>
  56. </httpHandlers><httpHandlers>
  57. <httpHandlers>
  58. <httpHandlers>
  59.    
  60. </httpHandlers>
  61. </httpHandlers>
  62. </httpHandlers><httpHandlers>
  63. <httpHandlers>
  64. <httpHandlers>
  65.    
  66. </httpHandlers>
  67. </httpHandlers>
  68. </httpHandlers><httpHandlers>
  69. <httpHandlers>
  70. <httpHandlers>
  71.    
  72. </httpHandlers>
  73. </httpHandlers>
  74. </httpHandlers>url: "/AjaxServices/GetMd5.aspx",<httpHandlers>
  75. <httpHandlers>
  76. <httpHandlers>
  77.    
  78. </httpHandlers>
  79. </httpHandlers>
  80. </httpHandlers><httpHandlers>
  81. <httpHandlers>
  82. <httpHandlers>
  83.    
  84. </httpHandlers>
  85. </httpHandlers>
  86. </httpHandlers><httpHandlers>
  87. <httpHandlers>
  88. <httpHandlers>
  89.    
  90. </httpHandlers>
  91. </httpHandlers>
  92. </httpHandlers><httpHandlers>
  93. <httpHandlers>
  94. <httpHandlers>
  95.    
  96. </httpHandlers>
  97. </httpHandlers>
  98. </httpHandlers>//url: "/AjaxServices.GetMd5.aspx",<httpHandlers>
  99. <httpHandlers>
  100. <httpHandlers>
  101.    
  102. </httpHandlers>
  103. </httpHandlers>
  104. </httpHandlers><httpHandlers>
  105. <httpHandlers>
  106. <httpHandlers>
  107.    
  108. </httpHandlers>
  109. </httpHandlers>
  110. </httpHandlers><httpHandlers>
  111. <httpHandlers>
  112. <httpHandlers>
  113.    
  114. </httpHandlers>
  115. </httpHandlers>
  116. </httpHandlers><httpHandlers>
  117. <httpHandlers>
  118. <httpHandlers>
  119.    
  120. </httpHandlers>
  121. </httpHandlers>
  122. </httpHandlers><httpHandlers>
  123. <httpHandlers>
  124. <httpHandlers>
  125.    
  126. </httpHandlers>
  127. </httpHandlers>
  128. </httpHandlers><httpHandlers>
  129. <httpHandlers>
  130. <httpHandlers>
  131.    
  132. </httpHandlers>
  133. </httpHandlers>
  134. </httpHandlers><httpHandlers>
  135. <httpHandlers>
  136. <httpHandlers>
  137.    
  138. </httpHandlers>
  139. </httpHandlers>
  140. </httpHandlers><httpHandlers>
  141. <httpHandlers>
  142. <httpHandlers>
  143.    
  144. </httpHandlers>
  145. </httpHandlers>
  146. </httpHandlers>// 注意:下面的二种type的设置也都是可以使用的。<httpHandlers>
  147. <httpHandlers>
  148. <httpHandlers>
  149.    
  150. </httpHandlers>
  151. </httpHandlers>
  152. </httpHandlers><httpHandlers>
  153. <httpHandlers>
  154. <httpHandlers>
  155.    
  156. </httpHandlers>
  157. </httpHandlers>
  158. </httpHandlers><httpHandlers>
  159. <httpHandlers>
  160. <httpHandlers>
  161.    
  162. </httpHandlers>
  163. </httpHandlers>
  164. </httpHandlers><httpHandlers>
  165. <httpHandlers>
  166. <httpHandlers>
  167.    
  168. </httpHandlers>
  169. </httpHandlers>
  170. </httpHandlers>type: "POST",<httpHandlers>
  171. <httpHandlers>
  172. <httpHandlers>
  173.    
  174. </httpHandlers>
  175. </httpHandlers>
  176. </httpHandlers><httpHandlers>
  177. <httpHandlers>
  178. <httpHandlers>
  179.    
  180. </httpHandlers>
  181. </httpHandlers>
  182. </httpHandlers><httpHandlers>
  183. <httpHandlers>
  184. <httpHandlers>
  185.    
  186. </httpHandlers>
  187. </httpHandlers>
  188. </httpHandlers><httpHandlers>
  189. <httpHandlers>
  190. <httpHandlers>
  191.    
  192. </httpHandlers>
  193. </httpHandlers>
  194. </httpHandlers> //type: "GET",<httpHandlers>
  195. <httpHandlers>
  196. <httpHandlers>
  197.    
  198. </httpHandlers>
  199. </httpHandlers>
  200. </httpHandlers><httpHandlers>
  201. <httpHandlers>
  202. <httpHandlers>
  203.    
  204. </httpHandlers>
  205. </httpHandlers>
  206. </httpHandlers><httpHandlers>
  207. <httpHandlers>
  208. <httpHandlers>
  209.    
  210. </httpHandlers>
  211. </httpHandlers>
  212. </httpHandlers><httpHandlers>
  213. <httpHandlers>
  214. <httpHandlers>
  215.    
  216. </httpHandlers>
  217. </httpHandlers>
  218. </httpHandlers><httpHandlers>
  219. <httpHandlers>
  220. <httpHandlers>
  221.    
  222. </httpHandlers>
  223. </httpHandlers>
  224. </httpHandlers><httpHandlers>
  225. <httpHandlers>
  226. <httpHandlers>
  227.    
  228. </httpHandlers>
  229. </httpHandlers>
  230. </httpHandlers><httpHandlers>
  231. <httpHandlers>
  232. <httpHandlers>
  233.    
  234. </httpHandlers>
  235. </httpHandlers>
  236. </httpHandlers><httpHandlers>
  237. <httpHandlers>
  238. <httpHandlers>
  239.    
  240. </httpHandlers>
  241. </httpHandlers>
  242. </httpHandlers> data: { str: $("#txtInput").val() },<httpHandlers>
  243. <httpHandlers>
  244. <httpHandlers>
  245.    
  246. </httpHandlers>
  247. </httpHandlers>
  248. </httpHandlers><httpHandlers>
  249. <httpHandlers>
  250. <httpHandlers>
  251.    
  252. </httpHandlers>
  253. </httpHandlers>
  254. </httpHandlers><httpHandlers>
  255. <httpHandlers>
  256. <httpHandlers>
  257.    
  258. </httpHandlers>
  259. </httpHandlers>
  260. </httpHandlers><httpHandlers>
  261. <httpHandlers>
  262. <httpHandlers>
  263.    
  264. </httpHandlers>
  265. </httpHandlers>
  266. </httpHandlers>dataType: "text",<httpHandlers>
  267. <httpHandlers>
  268. <httpHandlers>
  269.    
  270. </httpHandlers>
  271. </httpHandlers>
  272. </httpHandlers><httpHandlers>
  273. <httpHandlers>
  274. <httpHandlers>
  275.    
  276. </httpHandlers>
  277. </httpHandlers>
  278. </httpHandlers><httpHandlers>
  279. <httpHandlers>
  280. <httpHandlers>
  281.    
  282. </httpHandlers>
  283. </httpHandlers>
  284. </httpHandlers><httpHandlers>
  285. <httpHandlers>
  286. <httpHandlers>
  287.    
  288. </httpHandlers>
  289. </httpHandlers>
  290. </httpHandlers>success: function(responseText){<httpHandlers>
  291. <httpHandlers>
  292. <httpHandlers>
  293.    
  294. </httpHandlers>
  295. </httpHandlers>
  296. </httpHandlers><httpHandlers>
  297. <httpHandlers>
  298. <httpHandlers>
  299.    
  300. </httpHandlers>
  301. </httpHandlers>
  302. </httpHandlers><httpHandlers>
  303. <httpHandlers>
  304. <httpHandlers>
  305.    
  306. </httpHandlers>
  307. </httpHandlers>
  308. </httpHandlers><httpHandlers>
  309. <httpHandlers>
  310. <httpHandlers>
  311.    
  312. </httpHandlers>
  313. </httpHandlers>
  314. </httpHandlers><httpHandlers>
  315. <httpHandlers>
  316. <httpHandlers>
  317.    
  318. </httpHandlers>
  319. </httpHandlers>
  320. </httpHandlers>$("#md5Result").text(responseText);<httpHandlers>
  321. <httpHandlers>
  322. <httpHandlers>
  323.    
  324. </httpHandlers>
  325. </httpHandlers>
  326. </httpHandlers><httpHandlers>
  327. <httpHandlers>
  328. <httpHandlers>
  329.    
  330. </httpHandlers>
  331. </httpHandlers>
  332. </httpHandlers><httpHandlers>
  333. <httpHandlers>
  334. <httpHandlers>
  335.    
  336. </httpHandlers>
  337. </httpHandlers>
  338. </httpHandlers><httpHandlers>
  339. <httpHandlers>
  340. <httpHandlers>
  341.    
  342. </httpHandlers>
  343. </httpHandlers>
  344. </httpHandlers>}<httpHandlers>
  345. <httpHandlers>
  346. <httpHandlers>
  347.    
  348. </httpHandlers>
  349. </httpHandlers>
  350. </httpHandlers><httpHandlers>
  351. <httpHandlers>
  352. <httpHandlers>
  353.    
  354. </httpHandlers>
  355. </httpHandlers>
  356. </httpHandlers><httpHandlers>
  357. <httpHandlers>
  358. <httpHandlers>
  359.    
  360. </httpHandlers>
  361. </httpHandlers>
  362. </httpHandlers>});<httpHandlers>
  363. <httpHandlers>
  364. <httpHandlers>
  365.    
  366. </httpHandlers>
  367. </httpHandlers>
  368. </httpHandlers><httpHandlers>
  369. <httpHandlers>
  370. <httpHandlers>
  371.    
  372. </httpHandlers>
  373. </httpHandlers>
  374. </httpHandlers>});});
复制代码
注意:在path中直接使用某个扩展名的好处是不受配置项的顺序影响,而且容易理解,因为可读性较好。
这里要补充一点:MySimpleServiceFramework是我在博客【用Asp.net写自己的服务框架】中实现的那个框架。
在服务端,可以使用下面的代码来处理前面客户端发出的请求:
  1. [MyService]public class AjaxServices{<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>[MyServiceMethod]<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>public string GetMd5(string str)<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers>{<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers><httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>if( str == null )<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers><httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers><httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers>str = string.Empty;<httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers><httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers>byte[] bb = (new MD5CryptoServiceProvider()).ComputeHash(Encoding.Default.GetBytes(str));<httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers><httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers>return BitConverter.ToString(bb).Replace("-", "");<httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers>}}
复制代码
前面的示例配置中:path="Ajax*.*.aspx,Ajax*/*.aspx" ,我使用了aspx这个扩展名。
我想大家都知道aspx这个扩展名是ASP.NET可处理的扩展名,为什么我还可以使用呢?
其实这个问题的答案在我前面的截图以及FindMapping的实现代码中:由于我们指定的配置要优先于ASP.NET的默认配置,所以先有机会参与匹配,并能匹配成功。
小结:在GetHandlerMapping()过程中,会根据请求的URL地址以及HTTP调用动作(GET,POST),返回一个在定义的配置项(HttpHandlerAction类型)。
GetFactory()

在GetHandlerMapping()返回一个HttpHandlerAction的配置项后,HttpApplication会调用this.GetFactory(mapping);获取一个IHttpHandlerFactory ,本小节将来分析这个过程。
首先,我们还是来看一下GetFactory的实现代码:
  1. private Hashtable _handlerFactories = new Hashtable();private IHttpHandlerFactory GetFactory(HttpHandlerAction mapping){<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>// 先尝试从内部缓存中获取<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>HandlerFactoryCache cache = (HandlerFactoryCache) this._handlerFactories[mapping.Type];<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers>if (cache == null)<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers>{<httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers><httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers>// 创建一个缓存项并保存<httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers><httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers>cache = new HandlerFactoryCache(mapping);<httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers><httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers>this._handlerFactories[mapping.Type] = cache;<httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers>}<httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers>// 返回工厂对象<httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers>return cache.Factory;}
复制代码
代码中做了哪些事情,我在注释中有说明。这个方法的最后一定会返回一个IHttpHandlerFactory的实例。

看到这里,您觉得奇怪吗?
可能我们仅仅只是实现了一个自定义的IHttpHanlder接口,并没有实现IHttpHandlerFactory,那么ASP.NET是如何处理的呢?
请注意 new HandlerFactoryCache(mapping) 这行代码,这可不是简单地创建一个缓存对象,具体实现代码如下:
  1. internal class HandlerFactoryCache{<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>private IHttpHandlerFactory _factory;<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>internal HandlerFactoryCache(HttpHandlerAction mapping)<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers>{<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers><httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>// 根据HttpHandlerAction配置中的type字符串创建对应类型的对象<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers><httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers>object obj2 = mapping.Create();<httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers><httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers>if( obj2 is IHttpHandler ) {<httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers><httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers><httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers>// 如果我们的配置是一个IHttpHandler,<httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers><httpHandlers>
  80. <httpHandlers>
  81. <httpHandlers>
  82.    
  83. </httpHandlers>
  84. </httpHandlers>
  85. </httpHandlers><httpHandlers>
  86. <httpHandlers>
  87. <httpHandlers>
  88.    
  89. </httpHandlers>
  90. </httpHandlers>
  91. </httpHandlers>// 那么ASP.NET会为我们包装成一个HandlerFactoryWrapper<httpHandlers>
  92. <httpHandlers>
  93. <httpHandlers>
  94.    
  95. </httpHandlers>
  96. </httpHandlers>
  97. </httpHandlers><httpHandlers>
  98. <httpHandlers>
  99. <httpHandlers>
  100.    
  101. </httpHandlers>
  102. </httpHandlers>
  103. </httpHandlers><httpHandlers>
  104. <httpHandlers>
  105. <httpHandlers>
  106.    
  107. </httpHandlers>
  108. </httpHandlers>
  109. </httpHandlers>this._factory = new HandlerFactoryWrapper((IHttpHandler)obj2, this.GetHandlerType(mapping));<httpHandlers>
  110. <httpHandlers>
  111. <httpHandlers>
  112.    
  113. </httpHandlers>
  114. </httpHandlers>
  115. </httpHandlers><httpHandlers>
  116. <httpHandlers>
  117. <httpHandlers>
  118.    
  119. </httpHandlers>
  120. </httpHandlers>
  121. </httpHandlers>}<httpHandlers>
  122. <httpHandlers>
  123. <httpHandlers>
  124.    
  125. </httpHandlers>
  126. </httpHandlers>
  127. </httpHandlers><httpHandlers>
  128. <httpHandlers>
  129. <httpHandlers>
  130.    
  131. </httpHandlers>
  132. </httpHandlers>
  133. </httpHandlers>else {<httpHandlers>
  134. <httpHandlers>
  135. <httpHandlers>
  136.    
  137. </httpHandlers>
  138. </httpHandlers>
  139. </httpHandlers><httpHandlers>
  140. <httpHandlers>
  141. <httpHandlers>
  142.    
  143. </httpHandlers>
  144. </httpHandlers>
  145. </httpHandlers><httpHandlers>
  146. <httpHandlers>
  147. <httpHandlers>
  148.    
  149. </httpHandlers>
  150. </httpHandlers>
  151. </httpHandlers>// 如果不是IHttpHandler以及IHttpHandlerFactory,就抛出异常<httpHandlers>
  152. <httpHandlers>
  153. <httpHandlers>
  154.    
  155. </httpHandlers>
  156. </httpHandlers>
  157. </httpHandlers><httpHandlers>
  158. <httpHandlers>
  159. <httpHandlers>
  160.    
  161. </httpHandlers>
  162. </httpHandlers>
  163. </httpHandlers><httpHandlers>
  164. <httpHandlers>
  165. <httpHandlers>
  166.    
  167. </httpHandlers>
  168. </httpHandlers>
  169. </httpHandlers>if( !(obj2 is IHttpHandlerFactory) ) {<httpHandlers>
  170. <httpHandlers>
  171. <httpHandlers>
  172.    
  173. </httpHandlers>
  174. </httpHandlers>
  175. </httpHandlers><httpHandlers>
  176. <httpHandlers>
  177. <httpHandlers>
  178.    
  179. </httpHandlers>
  180. </httpHandlers>
  181. </httpHandlers><httpHandlers>
  182. <httpHandlers>
  183. <httpHandlers>
  184.    
  185. </httpHandlers>
  186. </httpHandlers>
  187. </httpHandlers><httpHandlers>
  188. <httpHandlers>
  189. <httpHandlers>
  190.    
  191. </httpHandlers>
  192. </httpHandlers>
  193. </httpHandlers>throw new HttpException("Type_not_factory_or_handler");<httpHandlers>
  194. <httpHandlers>
  195. <httpHandlers>
  196.    
  197. </httpHandlers>
  198. </httpHandlers>
  199. </httpHandlers><httpHandlers>
  200. <httpHandlers>
  201. <httpHandlers>
  202.    
  203. </httpHandlers>
  204. </httpHandlers>
  205. </httpHandlers><httpHandlers>
  206. <httpHandlers>
  207. <httpHandlers>
  208.    
  209. </httpHandlers>
  210. </httpHandlers>
  211. </httpHandlers>}<httpHandlers>
  212. <httpHandlers>
  213. <httpHandlers>
  214.    
  215. </httpHandlers>
  216. </httpHandlers>
  217. </httpHandlers><httpHandlers>
  218. <httpHandlers>
  219. <httpHandlers>
  220.    
  221. </httpHandlers>
  222. </httpHandlers>
  223. </httpHandlers><httpHandlers>
  224. <httpHandlers>
  225. <httpHandlers>
  226.    
  227. </httpHandlers>
  228. </httpHandlers>
  229. </httpHandlers>this._factory = (IHttpHandlerFactory)obj2;<httpHandlers>
  230. <httpHandlers>
  231. <httpHandlers>
  232.    
  233. </httpHandlers>
  234. </httpHandlers>
  235. </httpHandlers><httpHandlers>
  236. <httpHandlers>
  237. <httpHandlers>
  238.    
  239. </httpHandlers>
  240. </httpHandlers>
  241. </httpHandlers>}<httpHandlers>
  242. <httpHandlers>
  243. <httpHandlers>
  244.    
  245. </httpHandlers>
  246. </httpHandlers>
  247. </httpHandlers>}
复制代码
代码中,我加入的注释已经回答了前面提出的问题:如果是一个IHttpHandler对象,ASP.NET会再创建一个HandlerFactoryWrapper对象来包装IHttpHandler对象,如果是IHttpHandlerFactory对象,则直接返回。
我们再来看一下HandlerFactoryWrapper的实现代码:
  1. internal class HandlerFactoryWrapper : IHttpHandlerFactory{<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>private IHttpHandler _handler;<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>private Type _handlerType;<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers>internal HandlerFactoryWrapper(IHttpHandler handler, Type handlerType)<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers>{<httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers><httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers>this._handler = handler;<httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers><httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers>this._handlerType = handlerType;<httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers>}<httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers>public IHttpHandler GetHandler(HttpContext context,<httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers><httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers><httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers><httpHandlers>
  80. <httpHandlers>
  81. <httpHandlers>
  82.    
  83. </httpHandlers>
  84. </httpHandlers>
  85. </httpHandlers><httpHandlers>
  86. <httpHandlers>
  87. <httpHandlers>
  88.    
  89. </httpHandlers>
  90. </httpHandlers>
  91. </httpHandlers><httpHandlers>
  92. <httpHandlers>
  93. <httpHandlers>
  94.    
  95. </httpHandlers>
  96. </httpHandlers>
  97. </httpHandlers><httpHandlers>
  98. <httpHandlers>
  99. <httpHandlers>
  100.    
  101. </httpHandlers>
  102. </httpHandlers>
  103. </httpHandlers><httpHandlers>
  104. <httpHandlers>
  105. <httpHandlers>
  106.    
  107. </httpHandlers>
  108. </httpHandlers>
  109. </httpHandlers> string requestType, string url, string pathTranslated)<httpHandlers>
  110. <httpHandlers>
  111. <httpHandlers>
  112.    
  113. </httpHandlers>
  114. </httpHandlers>
  115. </httpHandlers>{<httpHandlers>
  116. <httpHandlers>
  117. <httpHandlers>
  118.    
  119. </httpHandlers>
  120. </httpHandlers>
  121. </httpHandlers><httpHandlers>
  122. <httpHandlers>
  123. <httpHandlers>
  124.    
  125. </httpHandlers>
  126. </httpHandlers>
  127. </httpHandlers>if( this._handler == null )<httpHandlers>
  128. <httpHandlers>
  129. <httpHandlers>
  130.    
  131. </httpHandlers>
  132. </httpHandlers>
  133. </httpHandlers><httpHandlers>
  134. <httpHandlers>
  135. <httpHandlers>
  136.    
  137. </httpHandlers>
  138. </httpHandlers>
  139. </httpHandlers><httpHandlers>
  140. <httpHandlers>
  141. <httpHandlers>
  142.    
  143. </httpHandlers>
  144. </httpHandlers>
  145. </httpHandlers> this._handler = (IHttpHandler)HttpRuntime.CreateNonPublicInstance(this._handlerType);<httpHandlers>
  146. <httpHandlers>
  147. <httpHandlers>
  148.    
  149. </httpHandlers>
  150. </httpHandlers>
  151. </httpHandlers><httpHandlers>
  152. <httpHandlers>
  153. <httpHandlers>
  154.    
  155. </httpHandlers>
  156. </httpHandlers>
  157. </httpHandlers>return this._handler;<httpHandlers>
  158. <httpHandlers>
  159. <httpHandlers>
  160.    
  161. </httpHandlers>
  162. </httpHandlers>
  163. </httpHandlers>}<httpHandlers>
  164. <httpHandlers>
  165. <httpHandlers>
  166.    
  167. </httpHandlers>
  168. </httpHandlers>
  169. </httpHandlers>public void ReleaseHandler(IHttpHandler handler)<httpHandlers>
  170. <httpHandlers>
  171. <httpHandlers>
  172.    
  173. </httpHandlers>
  174. </httpHandlers>
  175. </httpHandlers>{<httpHandlers>
  176. <httpHandlers>
  177. <httpHandlers>
  178.    
  179. </httpHandlers>
  180. </httpHandlers>
  181. </httpHandlers><httpHandlers>
  182. <httpHandlers>
  183. <httpHandlers>
  184.    
  185. </httpHandlers>
  186. </httpHandlers>
  187. </httpHandlers>// 一个HttpHandler是否能重用,这里就是一个典型的实现方式<httpHandlers>
  188. <httpHandlers>
  189. <httpHandlers>
  190.    
  191. </httpHandlers>
  192. </httpHandlers>
  193. </httpHandlers><httpHandlers>
  194. <httpHandlers>
  195. <httpHandlers>
  196.    
  197. </httpHandlers>
  198. </httpHandlers>
  199. </httpHandlers>if( !this._handler.IsReusable )<httpHandlers>
  200. <httpHandlers>
  201. <httpHandlers>
  202.    
  203. </httpHandlers>
  204. </httpHandlers>
  205. </httpHandlers><httpHandlers>
  206. <httpHandlers>
  207. <httpHandlers>
  208.    
  209. </httpHandlers>
  210. </httpHandlers>
  211. </httpHandlers><httpHandlers>
  212. <httpHandlers>
  213. <httpHandlers>
  214.    
  215. </httpHandlers>
  216. </httpHandlers>
  217. </httpHandlers> this._handler = null;<httpHandlers>
  218. <httpHandlers>
  219. <httpHandlers>
  220.    
  221. </httpHandlers>
  222. </httpHandlers>
  223. </httpHandlers>}}
复制代码
小结:HttpApplication会根据web.config中的配置去查找一个匹配的IHttpHandlerFactory类型, 即使我们配置的是自定义的IHttpHandler类型,而不是IHttpHandlerFactory类型,调用过程依然如此。
GetHandler()

在ASP.NET中,定义了二个版本的HttpHandlerFactory接口,分别为:
  1. public interface IHttpHandlerFactory{<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>IHttpHandler GetHandler(HttpContext context,<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers><httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers><httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers><httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers><httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers><httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers><httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers> string requestType, string url, string pathTranslated);<httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers>void ReleaseHandler(IHttpHandler handler);}internal interface IHttpHandlerFactory2 : IHttpHandlerFactory{<httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers>IHttpHandler GetHandler(HttpContext context,<httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers><httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers><httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers><httpHandlers>
  80. <httpHandlers>
  81. <httpHandlers>
  82.    
  83. </httpHandlers>
  84. </httpHandlers>
  85. </httpHandlers><httpHandlers>
  86. <httpHandlers>
  87. <httpHandlers>
  88.    
  89. </httpHandlers>
  90. </httpHandlers>
  91. </httpHandlers><httpHandlers>
  92. <httpHandlers>
  93. <httpHandlers>
  94.    
  95. </httpHandlers>
  96. </httpHandlers>
  97. </httpHandlers><httpHandlers>
  98. <httpHandlers>
  99. <httpHandlers>
  100.    
  101. </httpHandlers>
  102. </httpHandlers>
  103. </httpHandlers> string requestType, VirtualPath virtualPath, string physicalPath);}
复制代码
设计IHttpHandlerFactory接口的目的是为了在创建和重用IHttpHandler对象时,保留了足够的扩展机会,而IHttpHandlerFactory2则是一个仅供微软使用的内部接口(因为VirtualPath类型的可见性也是internal)。
我们都知道aspx, ashx能直接处理HTTP请求,它们都实现了IHttpHandler接口。它们能处理HTTP请求也因为ASP.NET已经配置过它们。以下是它们的默认配置:
  1. <httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers><httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>
复制代码
有趣的是:PageHandlerFactory和SimpleHandlerFactory都实现了IHttpHandlerFactory2接口,因此,它们都可以根据要请求的路径创建一个IHttpHandler实例。
从ASP.NET的默认配置,我们也可以看到:type参数是可以设置为一个实现IHttpHandlerFactory接口的类型,而不一定要求是实现IHttpHandler接口的类型。
小结:HttpApplication在处理请求时,并不会直接创建一个IHttpHandler的实例,而是先获取一个IHttpHandlerFactory的对象,再以接口的形式调用GetHandler()方法来获取一个IHttpHandler实例。
IHttpHandler.IsReusable

IHttpHandler接口有个IsReusable属性。MSDN对这个属性的说明也非常简单:
获取一个值,该值指示其他请求是否可以使用 IHttpHandler 实例。
按照这个说明,当我们直接在创建一个实现IHttpHandler的类型,并在web.config中注册到一个自定义的扩展名时,情况会如何呢?
我们再来看一下前面所提过的示例代码(MyTestHandler的):
  1. public class MyTestHandler : IHttpHandler{<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>private Counter _counter = new Counter();<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>public bool IsReusable<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers>{<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers><httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>get { return true; }<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers>}<httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers>public void ProcessRequest(HttpContext context)<httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers>{<httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers><httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers>_counter.ShowCountAndRequestInfo(context);<httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers>}}
复制代码
web.config中的配置为:
  1. <httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>
复制代码
当我连续5次访问 http://localhost:51652/abc.test?id=1 时,会在浏览器中看到以下输出结果:
4.png

从这个截图来看,显然:MyTestHandler的实例被重用了。

我想很多人都创建过ashx文件,IDE会为我们创建一个实现了IHttpHandler接口的类型,在实现IsReusable属性时,一般都会这样:
  1. public bool IsReusable {<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>get {<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers><httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers>return false;<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers>}}
复制代码
有些人看到这个,会想:如果返回true,就可以重用IHttpHandler实例,达到优化性能的目的。但事实上,即使你在ashx中返回true也是无意义的,因为您可以试着这样去实现这个属性:
  1. public bool IsReusable{<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>get { throw new Exception("这里不起作用。"); }}
复制代码
如果您访问那个ashx,会发现:根本没有异常出现!
因此,我们可以得出一个结论:默认情况下,IsReusable不能决定一个ashx的实例是否能重用。
这个结果太奇怪了。为什么会这样呢?

前面我们看到*.ashx的请求交给SimpleHandlerFactory来创建相应的HttpHandler对象,然而当ASP.NET调用SimpleHandlerFactory.GetHandler()方法时,该方法会直接创建并返回我们实现的类型实例。换句话说:SimpleHandlerFactory根本不使用IHttpHandler.IsReusable的属性,因此,这种情况下,想重用ashx的实例是不可能的事,所以,即使我在实现IsReusable属性时,写上抛异常的语句,根本也不会被调用。
同样的事情还发在aspx页面的实例上,所以,在默认情况下,我们不可能重用aspx, ashx的实例。
至于aspx的实例不能重用,除了和PageHandlerFactory有关外,还与Page在实现IHttpHandler.IsReusable有关,以下是Page的实现方式:
  1. public bool IsReusable{<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>get { return false; }}
复制代码
从代码可以看到微软在Page是否重用上的明确想法:就是不允许重用!
由于Page的IsReusable属性我们平时看不到,我想没人对它的重用性有产生过疑惑,但ashx就不同了,它的IsReusable属性的代码是摆在我们面前的,任何人都可以看到它,试想一下:当有人发现把它设为true or false时都不起作用,会是个什么想法?估计很多人会郁闷。
小结:IHttpHandler.IsReusable并不能决定是否重用HttpHanlder !
实现自己的HttpHandlerFactory

通过前面的示例,我们也看到了,虽然IHttpHandler定义了一个IsReusable属性,但它并不能决定此类型的实例是否能得到重用。重不重用,其实是由HttpHandlerFactory来决定的。ashx的实例不能重用就是一个典型的例子。
下面我就来演示如何实现自己的HttpHandlerFactory来重用ashx的实例。示例代码如下(注意代码中的注释):
  1. internal class ReusableAshxHandlerFactory : IHttpHandlerFactory{<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>private Dictionary _cache<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers><httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers> = new Dictionary(200, StringComparer.OrdinalIgnoreCase);<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers>public IHttpHandler GetHandler(HttpContext context,<httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers><httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers><httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers><httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers><httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers><httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers><httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers> string requestType, string virtualPath, string physicalPath)<httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers>{<httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers><httpHandlers>
  80. <httpHandlers>
  81. <httpHandlers>
  82.    
  83. </httpHandlers>
  84. </httpHandlers>
  85. </httpHandlers>string cacheKey = requestType + virtualPath;<httpHandlers>
  86. <httpHandlers>
  87. <httpHandlers>
  88.    
  89. </httpHandlers>
  90. </httpHandlers>
  91. </httpHandlers><httpHandlers>
  92. <httpHandlers>
  93. <httpHandlers>
  94.    
  95. </httpHandlers>
  96. </httpHandlers>
  97. </httpHandlers>// 检查是否有缓存的实例(或者可理解为:被重用的实例)<httpHandlers>
  98. <httpHandlers>
  99. <httpHandlers>
  100.    
  101. </httpHandlers>
  102. </httpHandlers>
  103. </httpHandlers><httpHandlers>
  104. <httpHandlers>
  105. <httpHandlers>
  106.    
  107. </httpHandlers>
  108. </httpHandlers>
  109. </httpHandlers>IHttpHandler handler = null;<httpHandlers>
  110. <httpHandlers>
  111. <httpHandlers>
  112.    
  113. </httpHandlers>
  114. </httpHandlers>
  115. </httpHandlers><httpHandlers>
  116. <httpHandlers>
  117. <httpHandlers>
  118.    
  119. </httpHandlers>
  120. </httpHandlers>
  121. </httpHandlers>if( _cache.TryGetValue(cacheKey, out handler) == false ) {<httpHandlers>
  122. <httpHandlers>
  123. <httpHandlers>
  124.    
  125. </httpHandlers>
  126. </httpHandlers>
  127. </httpHandlers><httpHandlers>
  128. <httpHandlers>
  129. <httpHandlers>
  130.    
  131. </httpHandlers>
  132. </httpHandlers>
  133. </httpHandlers><httpHandlers>
  134. <httpHandlers>
  135. <httpHandlers>
  136.    
  137. </httpHandlers>
  138. </httpHandlers>
  139. </httpHandlers>// 根据请求路径创建对应的实例<httpHandlers>
  140. <httpHandlers>
  141. <httpHandlers>
  142.    
  143. </httpHandlers>
  144. </httpHandlers>
  145. </httpHandlers><httpHandlers>
  146. <httpHandlers>
  147. <httpHandlers>
  148.    
  149. </httpHandlers>
  150. </httpHandlers>
  151. </httpHandlers><httpHandlers>
  152. <httpHandlers>
  153. <httpHandlers>
  154.    
  155. </httpHandlers>
  156. </httpHandlers>
  157. </httpHandlers>Type handlerType = BuildManager.GetCompiledType(virtualPath);<httpHandlers>
  158. <httpHandlers>
  159. <httpHandlers>
  160.    
  161. </httpHandlers>
  162. </httpHandlers>
  163. </httpHandlers><httpHandlers>
  164. <httpHandlers>
  165. <httpHandlers>
  166.    
  167. </httpHandlers>
  168. </httpHandlers>
  169. </httpHandlers><httpHandlers>
  170. <httpHandlers>
  171. <httpHandlers>
  172.    
  173. </httpHandlers>
  174. </httpHandlers>
  175. </httpHandlers>// 确保一定是IHttpHandler类型<httpHandlers>
  176. <httpHandlers>
  177. <httpHandlers>
  178.    
  179. </httpHandlers>
  180. </httpHandlers>
  181. </httpHandlers><httpHandlers>
  182. <httpHandlers>
  183. <httpHandlers>
  184.    
  185. </httpHandlers>
  186. </httpHandlers>
  187. </httpHandlers><httpHandlers>
  188. <httpHandlers>
  189. <httpHandlers>
  190.    
  191. </httpHandlers>
  192. </httpHandlers>
  193. </httpHandlers>if( typeof(IHttpHandler).IsAssignableFrom(handlerType) == false )<httpHandlers>
  194. <httpHandlers>
  195. <httpHandlers>
  196.    
  197. </httpHandlers>
  198. </httpHandlers>
  199. </httpHandlers><httpHandlers>
  200. <httpHandlers>
  201. <httpHandlers>
  202.    
  203. </httpHandlers>
  204. </httpHandlers>
  205. </httpHandlers><httpHandlers>
  206. <httpHandlers>
  207. <httpHandlers>
  208.    
  209. </httpHandlers>
  210. </httpHandlers>
  211. </httpHandlers><httpHandlers>
  212. <httpHandlers>
  213. <httpHandlers>
  214.    
  215. </httpHandlers>
  216. </httpHandlers>
  217. </httpHandlers>throw new HttpException("要访问的资源没有实现IHttpHandler接口。");<httpHandlers>
  218. <httpHandlers>
  219. <httpHandlers>
  220.    
  221. </httpHandlers>
  222. </httpHandlers>
  223. </httpHandlers><httpHandlers>
  224. <httpHandlers>
  225. <httpHandlers>
  226.    
  227. </httpHandlers>
  228. </httpHandlers>
  229. </httpHandlers><httpHandlers>
  230. <httpHandlers>
  231. <httpHandlers>
  232.    
  233. </httpHandlers>
  234. </httpHandlers>
  235. </httpHandlers>// 创建实例,并保存到成员字段中<httpHandlers>
  236. <httpHandlers>
  237. <httpHandlers>
  238.    
  239. </httpHandlers>
  240. </httpHandlers>
  241. </httpHandlers><httpHandlers>
  242. <httpHandlers>
  243. <httpHandlers>
  244.    
  245. </httpHandlers>
  246. </httpHandlers>
  247. </httpHandlers><httpHandlers>
  248. <httpHandlers>
  249. <httpHandlers>
  250.    
  251. </httpHandlers>
  252. </httpHandlers>
  253. </httpHandlers>handler = (IHttpHandler)Activator.CreateInstance(handlerType, true);<httpHandlers>
  254. <httpHandlers>
  255. <httpHandlers>
  256.    
  257. </httpHandlers>
  258. </httpHandlers>
  259. </httpHandlers><httpHandlers>
  260. <httpHandlers>
  261. <httpHandlers>
  262.    
  263. </httpHandlers>
  264. </httpHandlers>
  265. </httpHandlers><httpHandlers>
  266. <httpHandlers>
  267. <httpHandlers>
  268.    
  269. </httpHandlers>
  270. </httpHandlers>
  271. </httpHandlers>// 如果handler要求重用,则保存它的引用。<httpHandlers>
  272. <httpHandlers>
  273. <httpHandlers>
  274.    
  275. </httpHandlers>
  276. </httpHandlers>
  277. </httpHandlers><httpHandlers>
  278. <httpHandlers>
  279. <httpHandlers>
  280.    
  281. </httpHandlers>
  282. </httpHandlers>
  283. </httpHandlers><httpHandlers>
  284. <httpHandlers>
  285. <httpHandlers>
  286.    
  287. </httpHandlers>
  288. </httpHandlers>
  289. </httpHandlers>if( handler.IsReusable )<httpHandlers>
  290. <httpHandlers>
  291. <httpHandlers>
  292.    
  293. </httpHandlers>
  294. </httpHandlers>
  295. </httpHandlers><httpHandlers>
  296. <httpHandlers>
  297. <httpHandlers>
  298.    
  299. </httpHandlers>
  300. </httpHandlers>
  301. </httpHandlers><httpHandlers>
  302. <httpHandlers>
  303. <httpHandlers>
  304.    
  305. </httpHandlers>
  306. </httpHandlers>
  307. </httpHandlers><httpHandlers>
  308. <httpHandlers>
  309. <httpHandlers>
  310.    
  311. </httpHandlers>
  312. </httpHandlers>
  313. </httpHandlers>_cache[cacheKey] = handler;<httpHandlers>
  314. <httpHandlers>
  315. <httpHandlers>
  316.    
  317. </httpHandlers>
  318. </httpHandlers>
  319. </httpHandlers><httpHandlers>
  320. <httpHandlers>
  321. <httpHandlers>
  322.    
  323. </httpHandlers>
  324. </httpHandlers>
  325. </httpHandlers>}<httpHandlers>
  326. <httpHandlers>
  327. <httpHandlers>
  328.    
  329. </httpHandlers>
  330. </httpHandlers>
  331. </httpHandlers><httpHandlers>
  332. <httpHandlers>
  333. <httpHandlers>
  334.    
  335. </httpHandlers>
  336. </httpHandlers>
  337. </httpHandlers>return handler;<httpHandlers>
  338. <httpHandlers>
  339. <httpHandlers>
  340.    
  341. </httpHandlers>
  342. </httpHandlers>
  343. </httpHandlers>}<httpHandlers>
  344. <httpHandlers>
  345. <httpHandlers>
  346.    
  347. </httpHandlers>
  348. </httpHandlers>
  349. </httpHandlers>public void ReleaseHandler(IHttpHandler handler)<httpHandlers>
  350. <httpHandlers>
  351. <httpHandlers>
  352.    
  353. </httpHandlers>
  354. </httpHandlers>
  355. </httpHandlers>{<httpHandlers>
  356. <httpHandlers>
  357. <httpHandlers>
  358.    
  359. </httpHandlers>
  360. </httpHandlers>
  361. </httpHandlers><httpHandlers>
  362. <httpHandlers>
  363. <httpHandlers>
  364.    
  365. </httpHandlers>
  366. </httpHandlers>
  367. </httpHandlers>// 不需要处理这个方法。<httpHandlers>
  368. <httpHandlers>
  369. <httpHandlers>
  370.    
  371. </httpHandlers>
  372. </httpHandlers>
  373. </httpHandlers>}}
复制代码
为了能让HttpHandlerFactory能在ASP.NET中运行,还需要在web.config中注册:
  1. <httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>
复制代码
有了这个配置后,我们可以创建一个Handler2.ashx来测试效果:
  1. using System;using System.Web;public class Handler2 : IHttpHandler {<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>private Counter _counter = new Counter();<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>public bool IsReusable<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers>{<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers><httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>get { return true; }<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers>}<httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers>public void ProcessRequest(HttpContext context)<httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers>{<httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers><httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers>_counter.ShowCountAndRequestInfo(context);<httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers>}}
复制代码
在多次访问Handler2.ashx后,我们可以看到以下效果:
5.png

再来看看按照IDE默认生成的IsReusable会在运行时出现什么结果。示例代码:
  1. using System;using System.Web;public class Handler1 : IHttpHandler {<httpHandlers>
  2. <httpHandlers>
  3. <httpHandlers>
  4.    
  5. </httpHandlers>
  6. </httpHandlers>
  7. </httpHandlers>private Counter _counter = new Counter();<httpHandlers>
  8. <httpHandlers>
  9. <httpHandlers>
  10.    
  11. </httpHandlers>
  12. </httpHandlers>
  13. </httpHandlers>public bool IsReusable<httpHandlers>
  14. <httpHandlers>
  15. <httpHandlers>
  16.    
  17. </httpHandlers>
  18. </httpHandlers>
  19. </httpHandlers>{<httpHandlers>
  20. <httpHandlers>
  21. <httpHandlers>
  22.    
  23. </httpHandlers>
  24. </httpHandlers>
  25. </httpHandlers><httpHandlers>
  26. <httpHandlers>
  27. <httpHandlers>
  28.    
  29. </httpHandlers>
  30. </httpHandlers>
  31. </httpHandlers>get {<httpHandlers>
  32. <httpHandlers>
  33. <httpHandlers>
  34.    
  35. </httpHandlers>
  36. </httpHandlers>
  37. </httpHandlers><httpHandlers>
  38. <httpHandlers>
  39. <httpHandlers>
  40.    
  41. </httpHandlers>
  42. </httpHandlers>
  43. </httpHandlers><httpHandlers>
  44. <httpHandlers>
  45. <httpHandlers>
  46.    
  47. </httpHandlers>
  48. </httpHandlers>
  49. </httpHandlers>// 如果在配置文件中启用ReusableAshxHandlerFactory,那么这里将会被执行。<httpHandlers>
  50. <httpHandlers>
  51. <httpHandlers>
  52.    
  53. </httpHandlers>
  54. </httpHandlers>
  55. </httpHandlers><httpHandlers>
  56. <httpHandlers>
  57. <httpHandlers>
  58.    
  59. </httpHandlers>
  60. </httpHandlers>
  61. </httpHandlers><httpHandlers>
  62. <httpHandlers>
  63. <httpHandlers>
  64.    
  65. </httpHandlers>
  66. </httpHandlers>
  67. </httpHandlers>// 可以尝试切换下面二行代码测试效果。<httpHandlers>
  68. <httpHandlers>
  69. <httpHandlers>
  70.    
  71. </httpHandlers>
  72. </httpHandlers>
  73. </httpHandlers><httpHandlers>
  74. <httpHandlers>
  75. <httpHandlers>
  76.    
  77. </httpHandlers>
  78. </httpHandlers>
  79. </httpHandlers><httpHandlers>
  80. <httpHandlers>
  81. <httpHandlers>
  82.    
  83. </httpHandlers>
  84. </httpHandlers>
  85. </httpHandlers>//throw new Exception("这里不起作用。");<httpHandlers>
  86. <httpHandlers>
  87. <httpHandlers>
  88.    
  89. </httpHandlers>
  90. </httpHandlers>
  91. </httpHandlers><httpHandlers>
  92. <httpHandlers>
  93. <httpHandlers>
  94.    
  95. </httpHandlers>
  96. </httpHandlers>
  97. </httpHandlers><httpHandlers>
  98. <httpHandlers>
  99. <httpHandlers>
  100.    
  101. </httpHandlers>
  102. </httpHandlers>
  103. </httpHandlers>return false;<httpHandlers>
  104. <httpHandlers>
  105. <httpHandlers>
  106.    
  107. </httpHandlers>
  108. </httpHandlers>
  109. </httpHandlers><httpHandlers>
  110. <httpHandlers>
  111. <httpHandlers>
  112.    
  113. </httpHandlers>
  114. </httpHandlers>
  115. </httpHandlers>}<httpHandlers>
  116. <httpHandlers>
  117. <httpHandlers>
  118.    
  119. </httpHandlers>
  120. </httpHandlers>
  121. </httpHandlers>}<httpHandlers>
  122. <httpHandlers>
  123. <httpHandlers>
  124.    
  125. </httpHandlers>
  126. </httpHandlers>
  127. </httpHandlers>public void ProcessRequest(HttpContext context)<httpHandlers>
  128. <httpHandlers>
  129. <httpHandlers>
  130.    
  131. </httpHandlers>
  132. </httpHandlers>
  133. </httpHandlers>{<httpHandlers>
  134. <httpHandlers>
  135. <httpHandlers>
  136.    
  137. </httpHandlers>
  138. </httpHandlers>
  139. </httpHandlers><httpHandlers>
  140. <httpHandlers>
  141. <httpHandlers>
  142.    
  143. </httpHandlers>
  144. </httpHandlers>
  145. </httpHandlers>_counter.ShowCountAndRequestInfo(context);<httpHandlers>
  146. <httpHandlers>
  147. <httpHandlers>
  148.    
  149. </httpHandlers>
  150. </httpHandlers>
  151. </httpHandlers>}}
复制代码
此时,无论我访问Handler1.ashx多少次,浏览器始终显示如下结果:
6.png

如果我启用代码行 throw new Exception("这里不起作用。"); 将会看到以下结果:
7.png

终于,我们期待的黄页出现了。
此时,如果我在web.config中将ReusableAshxHandlerFactory的注册配置注释起来,发现Handler1.ashx还是可以访问的。
回想一下前面我们看到的IHttpHandlerFactory接口,它还定义了一个ReleaseHandler方法,这个方法又是做什么的呢?对于这个方法,MSDN也有一句简单的说明:
使工厂可以重用现有的处理程序实例。
对于这个说明,我认为并不恰当。如果按照HandlerFactoryWrapper的实现方式,那么这个解释是正确的。但我前面的示例中,我在实现这个方法时,没有任何代码,但一样可以达到重用HttpHandler的目的。因此,我认为重用的方式取决于具体的实现方式。
小结:IHttpHandler.IsReusable并不能完全决定HttpHandler的实例是否能重用,它只起到一个指示作用。HttpHandler如何重用,关键还是要由HttpHandlerFactory来实现。
是否需要IsReusable = true ?

经过前面文字讲解以及示例演示,有些人可能会想:我在实现IHttpHandler的IsReusable属性时,要不要返回true呢?(千万别模仿我的示例代码抛异常哦。
如果返回true,则HttpHandler能得到重用,或许某些场合下,是可以达到性能优化的目的。
但是,它也可能会引发新的问题:HttpHandler实例的一些状态会影响后续的请求。
也正是由于这个原因,aspx, ashx 的实例在默认情况下,都是不重用的。
有些人还可能会担心:被重用的HttpHandler是否有线程安全问题?
理论上,在ASP.NET中,只要使用static的数据成员都会有这个问题。不过,这里所说的被重用的单个HttpHandler实例在处理请求过程中,只会被一个线程所调用,因此,它的实例成员还是线程安全的。但有一点需要注意:在HttpHandlerFactory中实现重用HttpHandler时,缓存HttpHandler的容器要保证是线程安全的。
如果您希望重用HttpHandler来提升程序性能,那么我建议应该考虑以下问题:
HttpHandler的所有数据成员都能在处理请求前初始化。(通常会在后期维护时遗忘,尤其是多人维护时)
小结:在通常情况下,当实现IsReusable时返回false,虽然性能上不是最优,但却是最安全的做法。
HttpHandlerFactory的主要用途

前面示例演示了如何使用HttpHandlerFactory来重用HttpHandler,但设计HttpHandlerFactory并不是完全为了这个目的,它的主要用途还是如何创建HttpHandler,而且定义IHttpHandlerFactory的主要目的是为了扩展性。
我想很多人也许使用过 Web Service ,它运行在ASP.NET平台上,自然也有对应的HttpHandler,我们来看看asmx这个扩展名是如何映射的。
  1. [/code]接着找WebServiceHandlerFactory,最后发现是这样创建的HttpHandler :
  2. [code]internal IHttpHandler CoreGetHandler(Type type,<httpHandlers>
  3. <httpHandlers>
  4. <httpHandlers>
  5.    
  6. </httpHandlers>
  7. </httpHandlers>
  8. </httpHandlers><httpHandlers>
  9. <httpHandlers>
  10. <httpHandlers>
  11.    
  12. </httpHandlers>
  13. </httpHandlers>
  14. </httpHandlers> HttpContext context, HttpRequest request, HttpResponse response){<httpHandlers>
  15. <httpHandlers>
  16. <httpHandlers>
  17.    
  18. </httpHandlers>
  19. </httpHandlers>
  20. </httpHandlers>// ..... 已删除一些无关的代码<httpHandlers>
  21. <httpHandlers>
  22. <httpHandlers>
  23.    
  24. </httpHandlers>
  25. </httpHandlers>
  26. </httpHandlers>bool isAsync = protocol.MethodInfo.IsAsync;<httpHandlers>
  27. <httpHandlers>
  28. <httpHandlers>
  29.    
  30. </httpHandlers>
  31. </httpHandlers>
  32. </httpHandlers>bool enableSession = protocol.MethodAttribute.EnableSession;<httpHandlers>
  33. <httpHandlers>
  34. <httpHandlers>
  35.    
  36. </httpHandlers>
  37. </httpHandlers>
  38. </httpHandlers>if( isAsync ) {<httpHandlers>
  39. <httpHandlers>
  40. <httpHandlers>
  41.    
  42. </httpHandlers>
  43. </httpHandlers>
  44. </httpHandlers><httpHandlers>
  45. <httpHandlers>
  46. <httpHandlers>
  47.    
  48. </httpHandlers>
  49. </httpHandlers>
  50. </httpHandlers>if( enableSession ) {<httpHandlers>
  51. <httpHandlers>
  52. <httpHandlers>
  53.    
  54. </httpHandlers>
  55. </httpHandlers>
  56. </httpHandlers><httpHandlers>
  57. <httpHandlers>
  58. <httpHandlers>
  59.    
  60. </httpHandlers>
  61. </httpHandlers>
  62. </httpHandlers><httpHandlers>
  63. <httpHandlers>
  64. <httpHandlers>
  65.    
  66. </httpHandlers>
  67. </httpHandlers>
  68. </httpHandlers>return new AsyncSessionHandler(protocol);<httpHandlers>
  69. <httpHandlers>
  70. <httpHandlers>
  71.    
  72. </httpHandlers>
  73. </httpHandlers>
  74. </httpHandlers><httpHandlers>
  75. <httpHandlers>
  76. <httpHandlers>
  77.    
  78. </httpHandlers>
  79. </httpHandlers>
  80. </httpHandlers>}<httpHandlers>
  81. <httpHandlers>
  82. <httpHandlers>
  83.    
  84. </httpHandlers>
  85. </httpHandlers>
  86. </httpHandlers><httpHandlers>
  87. <httpHandlers>
  88. <httpHandlers>
  89.    
  90. </httpHandlers>
  91. </httpHandlers>
  92. </httpHandlers>return new AsyncSessionlessHandler(protocol);<httpHandlers>
  93. <httpHandlers>
  94. <httpHandlers>
  95.    
  96. </httpHandlers>
  97. </httpHandlers>
  98. </httpHandlers>}<httpHandlers>
  99. <httpHandlers>
  100. <httpHandlers>
  101.    
  102. </httpHandlers>
  103. </httpHandlers>
  104. </httpHandlers>if( enableSession ) {<httpHandlers>
  105. <httpHandlers>
  106. <httpHandlers>
  107.    
  108. </httpHandlers>
  109. </httpHandlers>
  110. </httpHandlers><httpHandlers>
  111. <httpHandlers>
  112. <httpHandlers>
  113.    
  114. </httpHandlers>
  115. </httpHandlers>
  116. </httpHandlers>return new SyncSessionHandler(protocol);<httpHandlers>
  117. <httpHandlers>
  118. <httpHandlers>
  119.    
  120. </httpHandlers>
  121. </httpHandlers>
  122. </httpHandlers>}<httpHandlers>
  123. <httpHandlers>
  124. <httpHandlers>
  125.    
  126. </httpHandlers>
  127. </httpHandlers>
  128. </httpHandlers>return new SyncSessionlessHandler(protocol);}
复制代码
这才是Factory嘛!
老实说,看到这几句话,我是眼前一亮:用HttpHandlerFactory来动态处理【是否支持Session】实在是太合适了。
这里有必要补充一下:
  1. internal class SyncSessionHandler : SyncSessionlessHandler, IRequiresSessionState
  2. {
  3. }
复制代码
小结:HttpHandlerFactory用途并非是为了专门处理HttpHandler的重用,它只是一个Factory,WebServiceHandlerFactory从另一个角度向我们展示了HttpHandlerFactory在扩展性方面所体现的重要作用。

点击此处下载示例代码
如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】按钮。
如果,您希望更容易地发现我的新博客,不妨点击一下右下角的【关注 Fish Li】。
因为,我的写作热情也离不开您的肯定支持。
感谢您的阅读,如果您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是Fish Li 。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册