ASP.Net内部处理机制

一、IIS服务器根据请求的文件的后缀名来确定如何处理这个请求。例如.html,或.js,或.aspx…服务器获取所请求的页面的后缀名后,在服务器端寻找可以处理这类后缀名的应用程序,如果IIS找不到可以处理此类文件的应用程序,并且这个文件也没有受到服务器端的保护(一个受保护的例子就是App_Code中的文件,一个不受保护的例子就是你的js脚本),那么IIS就直接把这个文件返回给客户端。

 

如果服务器找到了处理此类文件的应用程序,通常称为ISAPI(Internet Server Application Programe Interface,互联网服务器应用程序接口)应用程序,他实际上只是一个接口,起到一个代理的作用,它的主要工作是映射所请求的页面(文件)和与此后缀名相对应的实际的处理程序。

 

例如所有的.aspx文件实际上都是由aspnet_isapi.dll这个程序来处理的,当IIS把对于.aspx页面的请求提交给了aspnet_isapi.dll以后,它就不再关心这个请求随后是如何处理的了。Asp.net只是服务器(IIS)的一个组成部分而已,它是一个ISAPI扩展。

 

HttpRuntime类是asp.net的一个主要入口,它有一个称作ProcessRequest的方法,这个方法以一个HttpWorkerRequest类作为参数,HttpRuntime类几乎包含着关于单个Http请求的所有信息:所请求的文件、服务器变量、QueryString、Http头信息等等。Asp.net使用这些信息来加载、运行正确的文件,并且将这个请求转换到输出流中,一般来说,也就是HTML页面。

 

当web.config文件的内容发生改变,或者.aspx文件发生变动的时候,为了能够卸载运行在同一个进程中的应用程序,然后再重新加载,Http请求被分放在相互隔离的应用程序域中。HTTP.SYS的内置驱动程序来监听来自外部的HTTP请求,在操作系统启动的时候,IIS首先在HTTP.SYS中注册自己的虚拟路径。

 

如果请求是一个可访问的URL,HTTP.SYS会将这个请求交给IIS工作者进程。IIS6.0中叫做w3wp.exe,IIS5.0中叫做aspnet_wp.exe。

 

除了映射文件与其对应的处理程序外,ISAPI还需要做一些其他的工作:

1、从HTTP.SYS中获取当前的Http请求信息,并且将这些信息保存到HttpWorkerRequest类中。

2、在相互隔离的应用程序域AppDomain中加载HttpRuntime

3、调用 HttpRuntime的ProcessRequest方法。

接下来才是程序员通常编写的代码所完成的工作了,然后,IIS接收返回的数据流,并重新返还给 HTTP.SYS,最后,HTTP.SYS 再将这些数据返回给客户端浏览器。

 

二、当Http请求进入Asp.net RunTime以后,它的管道由托管模块(Managed Modules)和处理程序(Handlers)组成,并且由管道来处理这个Http请求。

 

按照图中的编号了解数据是如何流动的:

① HttpRuntime将Http请求转交给HttpApplication,HttpApplication代表着程序员创建的Web应用程序。HttpApplication创建针对此Http请求的HttpContext对象,这些HttpContext对象包含了关于此请求的诸多其他对象,主要有HttpRequest、HttpResponse、HttpSessionState等。这些对象在程序中可以通过Page类或者Context类进行访问。

② 接下来Http请求通过一系列Module,这些Module对Http请求具有完全的控制权这些Module可以做一些执行某个实际工作前的事情

③ Http请求经过所有的Module之后,它会被HttpHandler处理。

④ HttpHandler处理完以后,Http请求再一次回到Module,此时Module可以做一些某个工作已经完成了之后的事情。

三、Http管道中有两个可用的接口。一个是IHttpHandler,一个是IHttpModule。通过查看“处理程序映射”,发现好多文件都交给aspnet_isapi.dll去处理了。很明显,aspnet_isapi.dll不可能对每种文件采用同一种方式处理,所以在C:、WiNDOWSMicrosoft.NETFrameworkv2.0.50727Config目录下web.config文件中的<httpHandlers>节点中将不同的文件类型映射给不同的Handler去处理,对于.aspx来说,是由System.Web.UI.Page.HandlerFactory来处理。

 1 <httpHandlers>
 2 
 3             ……
 4 
 5             <add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="True" />
 6 
 7             <add path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" validate="True" />
 8 
 9             <add path="*.asmx" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="False" />
10 
11             <add path="*.rem" verb="*" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" validate="False" />
12 
13             <add path="*.soap" verb="*" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" validate="False" />
14 
15             <add path="*.asax" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
16 
17             <add path="*.ascx" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
18 
19             <add path="*.master" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
20 
21             ……
22 
23             <add path="*" verb="GET,HEAD,POST" type="System.Web.DefaultHttpHandler" validate="True" />
24 
25             <add path="*" verb="*" type="System.Web.HttpMethodNotAllowedHandler" validate="True" />
26 
27 </httpHandlers>

 

 

.Net Framework在处理Http请求时采用默认Handler,而如果要操控一个Http请求,就需要实现IHTTPHandler接口,而实现IHttpHandler接口的类就是一般处理程序。

 1 // 摘要:
 2 
 3     //     定义 ASP.NET 为使用自定义 HTTP 处理程序同步处理 HTTP Web 请求而实现的协定。
 4 
 5     public interface IHttpHandler
 6 
 7     {
 8 
 9        bool IsReusable { get; }
10 
11        void ProcessRequest(HttpContext context);
12 
13  }

 

该接口中包含一个属性和一个方法,其中ProcessRequest方法中的代码是处理请求的主要代码。IsReusable属性,该值指示其他请求是否可以使用IHttpHandler实例,也就是说后继的Http请求是不是可以继续使用实现了该接口的类的实例,为true时可以,否则不可以。下面是一个自定义的处理程序:

 1 public class Handler1 : IHttpHandler
 2     {
 3         public void ProcessRequest(HttpContext context)
 4         {
 5             //处理请求的代码
 6         }
 7         public bool IsReusable
 8         {
 9             get
10             {
11                 return true;
12             }
13         }
14 }

 

 

创建一个自定义的HttpHandler后,为了让它能够处理某些HTTP请求,还需要将它注册到web.config中:

1 <httpHandlers>
2 
3         <add verb="*" path="*.jpg" type="Test_js.Handler1"/>
4 
5 </httpHandlers>

 

path:指的是请求的文件名称,可以使用通配符扩大范围,也可以明确指定这个Handler仅用于处理某个特定的文件的请求。

verb:指的是请求此文件的方式,可以使post或get,用*代表所有的访问方式。

type:程序集.类名

IHttpFactory接口概述:

    

1 public interface IHttpHandlerFactory
2 
3     {
4 
5         IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated);
6 
7         void ReleaseHandler(IHttpHandler handler);
8 
9   }

 

GetHandler方法中的参数介绍:

context:System.Web.HttpContext 类的实例,它提供对用于为 HTTP 请求提供服务的内部服务器对象(如 Request、Response、Session和 Server)的引用。

requestType:客户端使用的 HTTP 数据传输方法(GET 或 POST)。

url:所请求资源的 System.Web.HttpRequest.RawUrl。

pathTranslated:所请求资源的 System.Web.HttpRequest.PhysicalApplicationPath。

 

该接口中定义了2个方法,GetHandler方法在请求开始的时候被调用,而ReleaseHandler在请求结束,所有的Handler都不在需要的时候被调用。

一个HandlerFactory可以处理N个HttpHandler,什么时候该处理什么HttpHandler就在这里的处理逻辑中实现。

 

什么时候使用IHttpHandlerFactory:

1、在一个项目中需要使用很多IHttpHandler的时候,而且对这些IHttpHandler判断都重复做一个同样的前期处理。

2、从部署和松散耦合考虑,如果你的web application足够大,你就要考虑在更换HttpHandler处理类的时候该不该去改动Web.config的配置,这种改动将会重新启动整个app,对于一些系统而言这是不可以随便进行的。这个时候,统一一个入口的IHttpHandlerFactory很重要,这个入口相对不变,而IHttpHandler实现可以通过外挂自定义的xml文件来实现松散耦合,运用一些反射什么的就可以实现了。

三、HttpModule是实现了IHttpModule接口的程序集,HttpModule的作用是与应用程序事件相关的。

    

1 public interface IHttpModule
2 
3     {
4 
5         void Dispose();
6 
7         void Init(HttpApplication context);
8 
9 }

 

Init()方法:这个方法接受一个HttpApplication对象,HttpApplication代表了当前的应用程序,在这个方法中注册对事件进行注册。

Dispose():它可以在进行垃圾回收之前进行一些清理工作。

通过在Http请求管道中注册期望对应用程序事件作出反应的方法,在相应的事件触发的时候,便会调用HttpModule注册了的方法,实际的工作在这些方法中执行。

 

自定义的HttpModule需要我们自己在web.config文件中对其进行注册:

 

1 <system.webServer>
2     <modules>
3       <add name="MyModule" type="WebApplication1.ModuleDemo,WebApplication1"/>
4     </modules>
5   </system.webServer>

整个过程:

1、当站点第一个资源被访问的时候,Asp.Net会创建HttpApplication类的实例,它代表着站点应用程序,同时会创建所有在Web.Config中注册过的Module实例。

2、在创建Module实例的时候会调用Module的Init()方法。

3、在Init()方法内,对想要作出响应的HttpApplication暴露出的事件进行注册。(仅仅进行方法的简单注册,实际的方法需要另写)。

4、HttpApplication在其应用程序周期中触发各类事件。

5、触发事件的时候调用Module在其Init()方法中注册过的方法

原文地址:https://www.cnblogs.com/hwy2014/p/4108177.html