使用C#写MVC框架(一:核心原理) HttpHandler

摘要:
这两个组件分别继承Ihtmodule和IhttpHandler接口,并且熟悉Asp-Friends of the Net管道事件。应该记住这两个接口。123456789101112131415161718192021222324252627处理请求时,HttpApplication类将执行以下事件。想要扩展HttpApplication类的开发人员需要特别注意这些事件。天冬氨酸。Net管道事件表明,在整个管道事件中有两个重要角色:HttpHandler和HttpModule。Asp.net中常见的httphandler类型?

https://www.cnblogs.com/pandorabox/p/10477426.html

使用C#写MVC框架(一:核心原理)


目录:

一、MVC原理解析

二、HttpHandler

       1.HttpHandler,IHttpHandler,MvcHandler的说明

       2.IHttpHandler解析

       3.MvcHandler解析

三、HttpModule

       1.HttpModule能干什么

       2.HttpModule的使用

       3.HttpModyle和HttpHandler如何区分

       4.UrlRoutingModule解析

一、MVC原理解析

当我们收到一个URL的请求是,服务端收到请求,主要经历以下几个步骤:

1.请求被UrlRoutingModule部件拦截

2.封装请求上下文HttpContext,成为HttpContextWrapper对象

3.根据当前的HttpContext,从Routes集合中得到与当前请求URL相符合的RouteData对象

4.将RouteData与HttpContext请求封装成一个RequestContext对象

5.根据RequestContext对象,从RouteData的RouteHandler中获取IHttpHandler(MVC里面会有一个IHttpHandler的实现类MvcHandler)。

6.执行IHttpHandler(MVCHandler),然后就是通过反射激活具体的controller,执行具体的action。

使用C#写MVC框架(一:核心原理) HttpHandler第1张

1.整个过程有两个核心的组件。UrlRoutingModule和MvcHandler,上文提到的各个过程都和两个组件有紧密的联系。而这两个组件分别继承Ihhtmodule和IhttpHandler接口,熟悉Asp.Net管线事件的朋友应该记得这两个接口。

2.UrlRoutingModule的作用可以理解为通过一系列的与路由相关的组件去解析当前请求的Controller与Action名称,其实简单点理解,比如我们请求的http://localhost:8080/Home/Index这个url的时候,UrlRoutingModule拦截到这个请求,然后通过一系列的方式得到这里的“Home"和”Index"

3.MvcHandler的作用就更加直接,上述通过拦截组件得到了请求的Controller和Action的名称,MvcHandler组件将当前请求的Controller名称反射得到对应的控制器对象,然后执行对应的Action方法。比如还是上述http:/localhost:8080/Home/Index这个请求,通过字符串“Home”反射成为Home这个类型的控制器对象,然后调用这个对象的Index()方法。

4.综上,联合这两个组件来理解,UrlRoutingModule组件的主要作用是解析当前的Controller与Action名称,MvcHandler的作用是将得到Controller名称激活,得到具体的Controller对象,然后执行对应的Action方法。

 二、HttpHandler

HttpHandler指所有实现IHttpHandler接口一类类型的统称,他是一个大的称谓。这些类型有一个共同的功能,那就可以用来处理http请求。

IHttpHandler是微软定义的一类接口,用来约束所有能够处理的http的类型的接口规则

MVcHandler是MVc里面实现IHttpHandler接口的类型,也就是说,MvcHandler是Mvc里面处理Http请求的类型。

总而言之,HttpHandler只是一个逻辑称谓,它并不存在,而IhhtpHandler和MvcHandler是.net framework里面具体存在的接口和实现类,是前者的表现形式。

IHttpHandler解析

做过webform开发的应该直到,在asp.net的页面生命周期里面,一共有24个管线事件,完整的管线使劲按可参考msdn文档:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
在处理该请求时将由 HttpApplication 类执行以下事件。 希望扩展 HttpApplication 类的开发人员尤其需要注意这些事件。
1. 对请求进行验证,将检查浏览器发送的信息,并确定其是否包含潜在恶意标记。 有关更多信息,请参见 ValidateRequest 和脚本侵入概述。
2. 如果已在 Web.config 文件的 UrlMappingsSection 节中配置了任何 URL,则执行 URL 映射。
3. 引发 BeginRequest 事件。
4. 引发 AuthenticateRequest 事件。
5. 引发 PostAuthenticateRequest 事件。
6. 引发 AuthorizeRequest 事件。
7. 引发 PostAuthorizeRequest 事件。
8. 引发 ResolveRequestCache 事件。
9. 引发 PostResolveRequestCache 事件。
10. 根据所请求资源的文件扩展名(在应用程序的配置文件中映射),选择实现 IHttpHandler 的类,对请求进行处理。 如果该请求针对从 Page 类派生的对象(页),并且需要对该页进行编译,则 ASP.NET 会在创建该页的实例之前对其进行编译。
11. 引发 PostMapRequestHandler 事件。
12. 引发 AcquireRequestState 事件。
13. 引发 PostAcquireRequestState 事件。
14. 引发 PreRequestHandlerExecute 事件。
15. 为该请求调用合适的 IHttpHandler 类的 ProcessRequest 方法(或异步版 IHttpAsyncHandler.BeginProcessRequest)。 例如,如果该请求针对某页,则当前的页实例将处理该请求。
16. 引发 PostRequestHandlerExecute 事件。
17. 引发 ReleaseRequestState 事件。
18. 引发 PostReleaseRequestState 事件。
19. 如果定义了 Filter 属性,则执行响应筛选。
20. 引发 UpdateRequestCache 事件。
21. 引发 PostUpdateRequestCache 事件。
22. 引发 EndRequest 事件。
23. 引发 PreSendRequestHeaders 事件。
24. 引发 PreSendRequestContent 事件。
 
Asp.net管线事件说明

  在整个管线事件中,有两个重要的角色就是HttpHandler和HttpModule。

Asp.net 中常见的httphandler类型

1
2
3
4
5
6
7
8
publicinterfaceIHttpHandler
{
    // 定义一个处理当前http请求的方法
    voidProcessRequest(HttpContext context);
 
    // 指示当前实例是否可以再次使用
    boolIsReusable { get; }
}

  

接口的定义很简单,ProcessRequest()方法里面传一个当前请求的上下文对象去处理当前的http请求

为了处理异步请求,framework里面还定义了一个异步的IHttpHandler接口:

1
2
3
4
5
6
publicinterfaceIHttpAsyncHandler : IHttpHandler
{
    // Methods
    IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, objectextraData);
    voidEndProcessRequest(IAsyncResult result);
}

  

接口的两个方法应该也不难理解。

HttpHandler的主要作用是处理http请求,一般处理程序还记得吗,ashx。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
publicclassDemoHandler : IHttpHandler
    {
 
        publicvoidProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
 
            varusername = context.Request.QueryString["username"];
            varpassword = context.Request.QueryString["password"];
            if(username == "admin"&& password == "admin")
            {
                context.Response.Write("用户admin登录成功");
            }
            else
            {
                context.Response.Write("用户名或者密码错误");
            }
        }
 
        publicboolIsReusable
        {
            get
            {
                returnfalse;
            }
        }
    }

  

然后运行,通过http://localhost:8080/DemoHandler.ashx?username=admin&password=admin去访问一般处理程序,既可以得到正确的结果。

当然,除了这个,我们还有最常见的aspx页面

1
2
3
4
5
6
7
publicpartialclassTestPage : System.Web.UI.Page
    {
        protectedvoidPage_Load(objectsender, EventArgs e)
        {
 
        }
    }

  

将page类转到定义

使用C#写MVC框架(一:核心原理) HttpHandler第2张

发现原来page类也是继承ihttphandler,这就是为什么可以用地址http://localhost:8080/TestPage.aspx来访问这个页面的原因。当然,子类中的ProcessRequest()方法并没有显示的声明出来,因为在page类里面有一个virtual的虚方法,当然,你也可以显示的声明出来。

1
2
3
4
5
6
7
8
9
10
11
12
publicpartialclassTestPage : System.Web.UI.Page
    {
        protectedvoidPage_Load(objectsender, EventArgs e)
        {
 
        }
 
        publicvoidProcessRequest(HttpContext context)
        {
            context.Response.Write("你好");
        }
    }<br><br>

然后再运行你会发现这个时候请求会进到ProcessRequest()方法,而不会进入到Page_Load()里面了,至于原因,这和Page类里面的封装有关系。当然这不是本文的重点,本文要说明的是所有实现了IHttpHandler接口的类型都可以再ProcessRequest()方法黎曼处理当前的http请求。

当然,除了ashx和aspx之外,还有一类http的服务接口处理文件asmx也和IHttpHandler有着不可分割的联系,可以说,再asp.net里面,只要是处理http请求的地方,IhttpHandler几乎“无处不在"

当然,除了上述asp.net自带的HttpHandler之外,我们也可以自定义HttpHandler处理待定的请求。比如我们新建一个Demo.cs页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
publicclassDemoHandler:IHttpHandler
    {
        publicboolIsReusable
        {
            get{ returnfalse; }
        }
 
        publicvoidProcessRequest(HttpContext context)
        {
            context.Response.Write("从asex页面进来");
 
            //throw new NotImplementedException();
        }
    }

当然,要使用这个自定义的handler需要在web.config里面加上配置。

1
2
3
4
5
<system.webServer>
   <handlers>
        <add name="asex"verb="*"path="*.asex"type="MyTestMVC.DemoHandler, MyTestMVC"preCondition="integratedMode"/>
    </handlers>
</system.webServer>

 这个配置的意思就是所有的url一asex结尾的请求都交给DemoHandler这个类去处理

localhost:8080/DemoHandel.asex

页面就会显示内容

MvcHandler解析

上文介绍了那么多的KHttpHandler的用法,都是webform里面的一些实现,我们知道了所有实现了IHttpHandler的类都可以处理Http请求。同样在MVC里面。也定义了一个实现IhttpHandler接口的类型,MvcHandler,用于处理当前http请求。通过反编译工具可以看到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
publicclassMvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
{
    // 省略若干字段// 所有方法
    staticMvcHandler();
    publicMvcHandler(RequestContext requestContext);
    protectedinternalvirtualvoidAddVersionHeader(HttpContextBase httpContext);
    protectedvirtualIAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, objectstate);
    protectedinternalvirtualIAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, objectstate);
    protectedinternalvirtualvoidEndProcessRequest(IAsyncResult asyncResult);
    privatestaticstringGetMvcVersionString();
    protectedvirtualvoidProcessRequest(HttpContext httpContext);
    protectedinternalvirtualvoidProcessRequest(HttpContextBase httpContext);
    privatevoidProcessRequestInit(HttpContextBase httpContext, outIController controller, outIControllerFactory factory);
    privatevoidRemoveOptionalRoutingParameters();
    IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, objectextraData);
    voidIHttpAsyncHandler.EndProcessRequest(IAsyncResult result);
    voidIHttpHandler.ProcessRequest(HttpContext httpContext);
 
    // 省略若干属性
} 

MvcHandler实现了IHttpHandler,IHttpAsynHandler两个接口,异步请求这里先不做介绍。重点还是来看看ProcessRequest()方法

使用C#写MVC框架(一:核心原理) HttpHandler第3张

将HttpContext转换为HttpContextBase对象,继续转到定义

使用C#写MVC框架(一:核心原理) HttpHandler第4张

这里声明了一个IController和IControllerFactory对象,通过this.ProcessRequestInit()方法创建具体的Controller实例。我们将ProcessRequestInit()方法转到定义

使用C#写MVC框架(一:核心原理) HttpHandler第5张

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
privatevoidProcessRequestInit(HttpContextBase httpContext, outIController controller, outIControllerFactory factory)
        {
            //1.得到当前的上下文
            HttpContext current = HttpContext.Current;
            if(current != null&& ValidationUtility.IsValidationEnabled(current) == true) ValidationUtility.EnableDynamicValidation(current);
            this.AddVersionHeader(httpContext);
            this.RemoveOptionalRoutingParameters();
 
            //2.从路由对象RouteData中获取当前请求的Controller名称
            stringrequiredString = this.RequestContext.RouteData.GetRequiredString("controller");
 
            //3.得到Controller工厂对象
            factory = this.ControllerBuilder.GetControllerFactory();
 
            //4.根据当前RequestContext对象,从Controller工厂创建具体的Controller对象
            controller = factory.CreateController(this.RequestContext, requiredString);
            if(controller == null) thrownewInvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.ControllerBuilder_FactoryReturnedNull, newobject[] { factory.GetType(), requiredString }));
        }  

 通过上文的注释可以很好理解整个控制器的实例化过程。本打算看下Controller工厂如何创建以及控制器如何实例化,奈何部分反编译不了。我们暂且理解为反射吧。这些细节并不影响我们理解整个过程。

创建控制器成功之后,就是执行Action方法了,这个过程在上面反编译的第二张图片的controller.Execute(this.RequestContext);方法得到体现。所以,除去细节,理解mvchandler的ProcessRequest()方法并不是太难。

三、HttpModule

除了HttpHandler之外,asp.net里面还有另外一个重要的角色--HttpModule。和HttpHandler类似,HttpModule指所有实现了IhttpModule接口的一类类型的统称。至于HttpModule,IHttpModule,UroroutingModule各个名臣的含义和上述HttpHandler相同,在此不做重复说明。

1.httpmodule能干什么,通过上文,我们直到httphandler的作用非常明确:处理http请求,生成相应的结果

免责声明:文章转载自《使用C#写MVC框架(一:核心原理) HttpHandler》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇转载 web前端简历Spring中三个注解@PathVariable、@Param和@RequestParam间的区别下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

http原理

一、HTTP服务介绍 1 简述用户访网站流程 a 进行域名信息的DNS解析   dig +trace 获得www.oldboyedu.com  ip地址信息 b 进行与网站服务器建立连接,tcp三次握手过程 (syn ack SEQ ACK/状态转换 closed listen syn_sent  syn_rcvd established ) c 和网站...

1、AJAX里面status的值代表什么 2、get post 的区别 3、怎样把对象转化成字符串 4、闭包、继承、原型、原型链 5 、http传输协议 6、arguments是什么

1、AJAX里面status的值代表什么 在JavaScript里面写AJax的时,最关键的一步是对XMLHttpRequest对象建立监听,即使用“onreadystatechange”方法。监听的时候,要对XMLHttpRequest对象的请求状态进行判断,通常是判断readyState的值为4且status的值为200或者304时执行我们需要的操作...

前端http请求和常见的几个请求技术做具体的讲解

对于前端来说,请求是前端日常工作必备的,通过请求才能与后端进行数据交互,尤其在现在前后端分离的开发模式下,请求显得就更加重要。因此,对于前端开发者来说,掌握请求就很重要。下面将从http请求和常见的几个请求技术做具体的讲解 一、XMLHttpRequest         XMLHttpRequest一开始只是微软浏览器提供的一个接口,后来各大浏览器纷纷效...

Http 持久连接与 HttpClient 连接池

一、背景 HTTP协议是无状态的协议,即每一次请求都是互相独立的。因此它的最初实现是,每一个http请求都会打开一个tcp socket连接,当交互完毕后会关闭这个连接。 HTTP协议是全双工的协议,所以建立连接与断开连接是要经过三次握手与四次挥手的。显然在这种设计中,每次发送Http请求都会消耗很多的额外资源,即连接的建立与销毁。 于是,HTTP协议的也...

android绘图—Paint path 旋转

http://meteor6789.blog.163.com/blog/static/35040733201111193535153/ Piant 看一段代码: mPaint = new Paint();mPaint.setAntiAlias(true);//锯齿mPaint.setDither(true);//mPaint.setColor(0xFF3...

Android视图控件架构分析之View、ViewGroup

在Android中,视图控件大致被分为两类,即ViewGroup和View,ViewGroup控件作为父控件,包含并管理着子View,通过ViewGroup和View便形成了控件树,各个ViewGoup对象和View对象就是控件树中的节点。在控件树中,以树的深度来遍历查找对应的控件元素,同时,上层控件负责子控件的测量与绘制,并传递交互事件。 Android...