Asp.net本质论之HTTP请求处理程序

标签: asp.net

主题 概要
Asp.net Http请求处理程序
编辑 时间
新建 20171113
序号 参考资料
1 Asp.net本质论
2 https://www.cnblogs.com/RobbinHan/archive/2011/12/05/2270707.html

前面从介绍HttpApplication对像可知,HttpApplication有19个标准事件,在第8个事件PostMapRequestHandler(
https://msdn.microsoft.com/en-us/library/system.web.httpapplication.postmaprequesthandler(v=vs.110).aspx)触发的时候,标志着已经获取到了处理当前请求的处理程序对象,在第11个事件PreRequestHandlerExecute之后,HttpApplicaton将执行这个处理程序。那么,HttpApplicaton选择处理程序的依据是什么?什么对象可以作为处理程序?HttpApplication如何得到这个处理程序对象?

处理程序概述

前面知道,HttpApplication是在请求到达后,HttpRuntime通过应用程序对象池创建的一个用于处理请求的对象。

但是真正的处理请求是在处理程序这个环节,那么HttpApplication的作用是什么呢?我们可以将它看作请求到达处理程序和离开处理程序的一个管道,这个管道提供了统一处理所有请求的机制,使得我们可以在请求被真正处理之前和处理之后进行预处理和处理后的工作。而处理程序则负责完成实际的请求处理工作,对于网站开发程序员来说,大多数的开发工作是围绕着处理程序展开的。处理程序在不同的网站开发技术中,有着不同的名称,在ASP.NET中,称为HttpHandler。

在Asp.net中,所有处理程序类必须实现IHttpHandler或者IHttpAsyncHandler接口。

IHttpHandler的说明:
https://msdn.microsoft.com/zh-cn/library/system.web.ihttphandler(v=vs.110).aspx
定义如下:

public interface IHttpHandler

    {
        //  其他Request是否可以使用IHttpHandler
        bool IsReusable { get; }

        //  处理HttpRequest
        void ProcessRequest(HttpContext context);
    }

RrocessRequest是这个接口的主要方法,接收一个HttpContext类型的上下文对象,通过这个对象,处理程序可以得到关于处理请求所需的信息,通过这个参数的Response属性,可以得到管理回应的对象,用户向客户端返回服务器处理的结果。
IsReuseable属性表示这个处理程序对象在使用之后,是否还可以被缓存起来,在以后的请求处理程序中再次使用。

处理程序工厂

实现了处理程序接口的类就可以被用来创建处理程序对象直接使用,如果再配合一个处理程序工厂,就可以实现处理程序对象的管理。比如说,创建一个处理程序对象池,就可以不用在每次使用处理程序的时候创建一个新的对象,而是从池中取一个现有的对象直接使用,以提高效率。

处理程序工厂类必须实现接口,定义如下:
https://msdn.microsoft.com/zh-cn/library/system.web.ihttphandlerfactory(v=vs.110).aspx
这里写图片描述

其中,GetHandler方法用来通过这个处理程序工厂获取一个处理程序对象,ReleaseHandler方法用来释放一个处理程序对象。
常见的处理程序工厂:
这里写图片描述

注册处理程序

每一种处理程序用来处理一类的请求,不同的请求类别通过不同的扩展名来进行区分,处理程序与网站之间的匹配关系在网站的配置文件web.config中通过配置参数进行设置。
System.web配置元素的子元素httpHandlers用来配置网站所使用的处理程序。

一般处理程序

Asp.net自带的实现了IHttpHandler的处理程序,扩展名为*.ashx,这个处理程序已经定义在系统配置文件的web.config中,对于.net4.0的路径:
(C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config),
所以浏览器可以直接请求扩展名为ashx的地址:
这里写图片描述

通过配置文件,我们可以看到,对于扩展名为ashx的请求是通过定义在命名空间System.Web.UI下的SimpleHandlerFactory处理程序工厂来完成的。
当请求一个ashx扩展名的服务器资源时,SimpleHandlerFactory将找到对应的ashx文件,通过这个文件找到对应的处理程序。最后,SimpleHandlerFactory通过反射创建一个此类型的处理程序对象实例,并通过GetHandler方法返回HttpApplication,完成最终的请求处理过程。

页面处理程序

扩展名为aspx的请求,将由PageHandlerFactory这个处理程序工厂进行处理。

Web服务处理程序

对于Web服务来说,标准的方式是使用SOAP协议,在SOAP协议中,请求和响应的数据通过XML格式进行描述。在Asp.net 4.0下,对于Web服务来说,还可以选择支持Ajax访问。为了同时支持这两种类型的请求处理,在Asp.net 4.0下,处理程序工厂采用了两级结构。首先,通过标准的处理程序工厂来取得服务的处理程序;其次,在内部根据请求的内容来取得实际的处理程序工厂;最终,取得处理请求的处理程序。
这里写图片描述
在ScriptHandlerFactory内部,定义了两个处理程序工厂,RestHandlerFactory和WebServiceHandlerFactory,伪代码如下:
这里写图片描述

在ScriptHandlerFactory内部,通过GetHandler方法获取一个处理程序对象实例的时候,将首先判断请求是否是一个REST请求,根据判断的结果来决定当前实际使用的处理程序工厂。

MVC处理程序

在asp.net MVC2下,引入了Controller的概念,请求将被首先路由到Controller进行处理,然后由Controller分配到相应的Action完成实际的处理工作。处理的数据结果就是所谓的Modal。然后,这个Modal被传递给View转换成显示的界面元素,最终发送到客户端完成处理工作。

在Asp.net中,起着路由作用的处理程序不是一个普通的处理程序,因为对于MVC的请求来说根本就不是通过请求的扩展名来判断的,所以,这个处理程序通过一个类型为UrlRouting Module的Module配置在网站中,通过HttpApplication的事件管道得到这个处理程序。
这里写图片描述

在系统的配置文件中,可以看到确实配置了这个模块:
这里写图片描述

那么这个模块是什么时机起的作用呢,或者是从哪里开始拦截正常的Http请求的呢?

反编译dll(注:我并没有去反编译源码,Reflactor一直安装有问题,参考了
https://www.cnblogs.com/RobbinHan/archive/2011/12/05/2270707.html):

protected virtual void Init(HttpApplication application)

        {
            application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);

            application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler);

        }

可以看到,在PostResolveRequestCache,PostMapRequestHandler事件时进行了拦截。

拦截后,主要做了什么工作?

看OnApplicationPostResolveRequestCache这个方法:

public class UrlRoutingModule : IHttpModule
        {

            protected virtual void Init(HttpApplication application)
            {

                application.PostResolveRequestCache += OnApplicationPostResolveRequestCache;
            }

            private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
            {
                HttpContextBase context = new HttpContextWrapper(((HttpApplication)sender).Context);
                PostResolveRequestCache(context);
            }

            public virtual void PostResolveRequestCache(HttpContextBase context)
            {
                // Match the incoming URL against the route table
                RouteData routeData = RouteCollection.GetRouteData(context);

                // Do nothing if no route found 
                if (routeData == null)
                {
                    return;
                }

                // If a route was found, get an IHttpHandler from the route's RouteHandler 
                IRouteHandler= routeData.RouteHandler;
                RequestContext requestContext = new RequestContext(context, routeData);
                IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);

                // Remap IIS7 to our handler
                context.RemapHandler(httpHandler);
            }
        } 

总结起来,步骤是:
1)UrlRoutingModule在PostResolveRequestChche事件中做的第一件事就是包装当前的HttpContext为HttpContextWrapper。
(2)接着把HttpContextWrapper传给RouteTable,RouteTable根据参数返回一个匹配的路由对象:RouteData。
(3)如果UrlRoutingModule成功获取到RouteData,则会创建HttpContext对象和RouteData的RouteContext路由对象。
(4)然后把RouteContext路由对象传递给Handler的构造函数,实例化出一个新的HttpHandler;同时把此路由对象RouteContext通过HttpContext对象的Items集合保存起来,以便在PostMapRequestHandler中使用。

控制器的工厂接口IControllerFactory

前面通过UrlRoutingModule(实现IHttpModule接口)通过注册的路由表匹配得到了一个MvcRouteHandler(实现IRouteHandler接口),通过MvcRouteHandler创建一个MvcHandler(实现IHttpHandler接口)对象。而MvcHandler则要通过IControllerFactory对象,实现控制器的对象实例。

public interface IControllerFactory
    {
        IController CreateController(RequestContext requestContext, string controllerName);
        void ReleaseController(IController controller);
    }

MVC请求的处理过程

这里写图片描述
这里写图片描述

版权声明:本文为shaozhenged原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/shaozhenged/article/details/78519230

智能推荐

ASP.NET中使用一般处理程序ashx作为后台处理实现响应get和post请求

场景 ASP.NET中新建Web网站并部署到IIS上(详细图文教程): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/107199747 在上面博客中已经将网站部署到了IIS上。 怎样对前端的请求进行响应普通文本和JSON数据以及怎样获取get和post请求参数。 注: 博客: https://blog.csdn.net/bad...

.ashx一般处理程序【ASP.NET】

【.ashx 文件】 Asp.Net常用文件【牛腩】 我的这篇博客中做过相关介绍,就不过多阐述了… 在这篇博客的基础上,继续了解.ashx文件的作用。 【代码片段】 效果: 【.html模板文件】 通过上面的“小栗子”我们发现,如果想改变.ashx 呈现的样式,在.ashx改起来相当的麻烦。更何况,关于样式,应该是美工要做的事情,那么我们就可以创建一个.htm...

ASP.NET模块和处理程序 HttpHandler

在ASP.NET中可以很方便的创建HttpHandler的应用,现在使用HttpHandler来为图片增加水印。 数字水印的实现有3种方法: 1.直接编辑每张图片    需要大量的人力 2.编程实现批量编辑图片    效率高,不需要大量的人力,但是原图片会丢失 3.在显示图片时,动态添加数字水印效果    使用 Htt...

【C#本质论 五】方法和参数

前面四篇博客主要介绍了一些基本的操作内容,包含之前不了解的冷知识,以及一些新学到的C#较新版本的新知识,做个简单的小结: 新知识:元组、tryParse(out可内联)、字符串插值、空合并操作符、空条件操作符、可空修饰符、switch的模式匹配 冷知识:同类型单行声明赋值、字符串的不可变、字符串驻留技术、运算符优先级、预编译指令 对于个人来说还是小有帮助的,至少再看到一些奇怪的类似??的符号不会说...

TensorFlow架构与设计:OP本质论

作者:刘光聪 ,中兴通讯高级系统架构师,专注机器学习算法,分布式系统架构与优化。 原文:TensorFlow架构与设计:OP本质论 责编:王艺 CSDN AI记者,投稿、寻求报道、深入交流请邮件[email protected]或扫描文末二维码添加微信。 相关文章: 图解TensorFlow架构与设计 TensorFlow架构与设计:图模块 TensorFlow架构与设计:会话生命周期 TensorF...

猜你喜欢

【C#本质论 十一】合式类型(二)程序集引用、XML注释、垃圾回收和资源清理

上一节介绍到了如何进行Object方法重写和操作符重载,本篇博客来接着介绍合式类型剩余的内容: 程序集引用及命名空间定义 其中一些相对简单的内容就不进行过多的介绍了,例如引用其他程序集,只需要注意三种引用方式: 第一种方式是引用库项目文件,指出库的源代码在哪个项目中,并在两个项目之间建立依赖关系。编译好库之后才能编译引用了该库的程序。该依赖关系造成在编译程序时先编译库(如果还没有编译的话)项目拷贝...

ASP.NET Web API项目自定义接口路由和HTTP请求方式

在实际编写接口的过程中难免有一些特殊的接口,比如动态参数接口,以“JTT1078-2016道路运输车辆卫星定位系统视频通信协议(扫描版)”中的HTTP URL服务要求为例,截图如下: 定义API接口和请求方式 接口定义要满足需求,这里通过四种HTTP 请求方式。 配置指定接口的路由方式 运行项目查看定好的接口是否可行查看接口目录列表: 以GET请求方式为例,我们查看参数情况...

ABP Asp.net core 创建一个http get 请求

ABP Asp.net core 创建一个http  get 请求,携带token Post man 先调用一下试试,是通的  ...

冒泡排序,及改进方式,性能优化400%>>>附图解加源码

首先源码附上,源码中带有注释,看不懂没关系,源码后面附带图解,最后附上代码效率提升图 源码如下: 方案一:其实实现很简单,两层循环,每次内层迭代出最大的一个值,将其放入数组最后一个位置,外层循环的末端便往前移一位。其原理如下图 方案一代码块: 方案二:优化改进 仔细观察上面的图,我们不难发现当迭代到图下这样的情况时,其实已经全排序好了,但是我们还是需要对它进行1,2,3,4,5,6的迭代,这些情况...

css3常用选择器

先介绍一下基本选择器,如下几种 *:通配符。选择页面的所有元素 E:元素选择器。对页面的一些元素进行选择,如p,div,li等 .class:类选择器 #id:id选择器。一个Id在一个页面中只能选择,这是和类选择器的区别 E F:后代选择器。如ul li。选中ul下的li E>F:子元素选择器。如下,可以用 h1 > strong {color:red;}使h1的子元素strong变...