asp.net介绍

Asp.net不是asp的简单升级,而是微软。Net计划中的一个重要组成部分,它依托。Net的多语言与强大的类库支持,引进了服务端 HTML控件与WEB控件,自动处理控件的客户端与服务端的交互,为开发人员提供了类似Windows下窗口编程的界面,为开发大型网络应用程序功能提供了良好的编程接口,也能够极大地提高开发人员的工作效率。

然而,"一次转换,两次编译"过程使得aspx文件在首次执行(或更新后首次运行)时显得略有不足,特别是在拥有大量aspx及codebehind的代码文件的应用环境中,把aspx文件编译成DLL(在。Net中,被称为应用程序集)后再发布,省去"一次转换、一次编译"的时间及CPU占用率,对提高WEB服务的整体性能会有较大的提升。当然,编译成DLL后,对源代码的保密性也有一定程度的提高。

本文通过对Asp.Net的基本处理流程及一个偶然发现的秘密的分析,介绍了在Asp.Net中如何建立aspx到DLL的映射,如何开发一个可以处理HTTP请求/响应的DLL,以及如何设置"陷阱",把现成的单个aspx文件与 codebehind的aspx文件编译成DLL的过程,文章最后,还介绍了一个在实际操作过程的小技巧。

由于本文要涉及Asp.Net应用程序、命令行编译、web.config配置文件等概念,为了使读者能更好地理解本文内容,也为了使本文看上去不显累赘,先就本文相对应的系统环境作一介绍:

系统环境:Win2000(SP3)+ IIS5 + .Net Framework 1.0(中文版)。

服务器名称:由于本文的例子均在本机上测试,服务器名称为localhost.

IIS设置:建立虚拟目录dlltest(真实路径为w:\wwwroot\dlltest),并把它设为应用程序,在dlltest下建立bin目录。所有源文件将放在dlltest目录下,而所有dll文件将放在dlltest\bin目录下。

    Asp.Net应用程序配置文件——web.config在dlltest目录下建立一个web.config文件,初始时该文件内容如下:

<?xml version="1.0"?>
<configuration>
<system.web />
</configuration>

命令窗口(DOS窗口)

打开命令窗口,并用cd命令使当前目录为w:\wwwroot\dlltest.

(一)建立aspx到dll的映射

首先让我们来看看一般情况下aspx文件是如何被Asp.Net处理的:

当一个HTTP请求(例如"http://webserver/webapp/webpage.aspx")从客户端发送到IIS服务器时,IIS捕获并分析这个请求,

è当它分析到这个请求是一个aspx页面时,立即以 "/webapp/webpage.aspx"为参数调用Asp.Net运行环境(aspnet_wp.exe),

èAsp.Net环境启动后,检查 "/webapp/webpage.aspx"是否存在,若不存在,则向客户端返回HTTP 404(File not found)错误,

è否则在 Asp.Net 的临时目录中查找相应的dll文件,若不存在或者该dll比aspx源文件"旧",则调用csc编译器(若aspx的服务端脚本语言是 VB或JScript,则调用相应的vbc编译器, jsc编译器)把aspx文件编译成dll,

è然后Asp.Net再调用该dll来处理具体的客户请求,返回服务器响应。

从这个处理流程可以看出,一般情况下,Asp.Net运行环境会自动识别、检查、更新与aspx相对应的 dll.那么有没有其它办法可以强制把对一个aspx文件的处理"路由"到一个已编译存在的DLL呢?方法就是在Asp.Net应用程序配置文件 web.config的system.web节的httpHandlers节添加aspx到dll的映射项,语法如下:

    <add verb="*" path="aspx文件名" type="类名,dll文件" />

aspx文件:需要被"路由"的虚拟名称,扩展名必须是aspx,否则IIS会先于Asp.Net运行环境处理该文件。

dll文件: dll文件(应用程序集)的名称,不必输入".dll".ASP.NET 首先在应用程序的专用 \bin 目录中搜索程序集 DLL,然后在系统程序集缓存中搜索程序集 DLL.

类名: 由于一个dll可能会有多个名称空间或多个类,因此必须指明当dll调用时自动加载哪个类。

例如,某一Asp.Net应用程序的web.config文件如下:

<?xml version="1.0"?>
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="index.aspx" type="BBS.IndexPage, bbs" />
</httpHandlers>
</system.web>
</configuration>

该配置文件告诉Asp.Net,在客户端请求本应用程序的index.aspx文件时,直接调用应用程序bin目录下的bbs.dll,并自动加载其中的BBS.IndexPage类。

(二)开发能处理HTML页面的DLL

应该指出的是,并不是所有的应用程序集DLL都能实现HTTP请求/响应模式。还是来看一下Microsoft Asp.Net快速入门教程(http://chs.gotdotnet.com/quickstart/aspplus/)中关于"Http 处理程序和工厂"的描述:

    ASP.NET  提供低级别的请求/响应 API,使开发人员能够使用 .NET 框架类为传入的 HTTP 请求提供服务。为此,开发人员需创作支持  System.Web.IHTTPHandler 接口和实现 Proce***equest()方法的类。当处理 HTTP 请求不需要由高级别的页框架抽象化提供的服务时,处理程序通常很有用。处理程序的常用用途包括筛选器和类似 CGI 的应用程序,尤其是那些返回二进制数据的应用程序。

    ASP.NET  收到的每个传入 HTTP 请求最终由实现 IHTTPHandler 的类的特定实例来处理。IHttpHandlerFactory 提供了处理  IHttpHandler 实例 URL 请求的实际解析的结构。除了 ASP.NET 提供的默认 IHttpHandlerFactory 类外,开发人员还可以选择创建和注册工厂以支持大量的请求解析和激活方案。

从这段文字可以看出,当aspx页面不涉及。net框架提供的高级界面技术(如数据缓存、状态保持、Web窗体控件引用等等)时,且向客户端输出的不是复杂的HTML文本,特别是只向客户端返回二进制数据(如图片,声音等)时,可以用一个。cs应用程序文件(本文使用c#语言,如果是用VB或JScript,……)来替代,而该应用程序必须有一个实现 System.Web.IHTTPHandler 接口和并实现 Proce***equest()方法的类。一个简单的例子如下:

1
2 /* 源文件:ex1.cs 开始 */
3 using System.Web;
4 namespace DllTest
5 {
6 /*类必须实现IHttpHandler接口。如果程序将访问会话状态(Session),则必须实现 IRequiresSessionState 接口(不包含任何方法的标记接口)。*/
7
8
9 public class Ex1Page : IHttpHandler
10 {
11 /*IsReusable属性告诉。Net框架,本程序是否可以被多个线程同时使用。
12 true对应是;false对应否。*/
13
14 public bool IsReusable
15 {
16 get  { return true; }
17 }
18
19
20
21 /*实现Proce***equest方法,向客户端返回响应数据。
22 本例中向客户端返回一个简单的HTML页*/
23
24 public void Proce***equest(HttpContext context)
25 {
26 HttpResponse res = context.Response;
27
28 res.Write("<html><body>");
29 res.Write("<h1>DllTest - Ex1(例1)</h1><hr>");
30 res.Write("本页面直接由DLL处理");
31 res.Write("</html></body>");
32 }}}
33/* 源文件:ex1.cs 结束 */

在命令行状态,用如下的编译命令把ex1.cs编译成ex1.dll,并把它存放在bin目录下。

csc /t:library /out:bin\ex1.dll ex1.cs
可以但要写全路径
csc /t:library /out:j:\WebSite\WebTest\bin\ex1.dll
J:\WebSite\WebTest\App_Code\ex1.cs

在配置文件web.config中添加aspx-&gt;dll映射,添加后,web.config应该是这样子的:

<?xml version="1.0"?>
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="dlltest1.aspx" type="DllTest.ex1Page,ex1" />
</httpHandlers>
</system.web>
</configuration>

文章标签: asp.net iis 扩展 httpmodule webform webservice
版权
这篇文章以非常底层的视角讲述了Web请求(request)在ASP.NET框架中是如何流转的,从Web服务器,通过ISAPI直到请求处理器(handler)和你的代码.看看在幕后都发生了些什么,不要再把ASP.NET看成一个黑盒了.

ASP.NET是一个非常强大的构建Web应用的平台,它提供了极大的灵活性和能力以致于可 以用它来构建所有类型的Web应用.绝大多数的人只熟悉高层的框架如WebForms和WebServices-这些都在ASP.NET层次结构在最高 层.在这篇文章中我将会讨论ASP.NET的底层机制并解释请求(request)是怎么从Web服务器传送到ASP.NET运行时然后如何通过 ASP.NET管道来处理请求.

对我而言了解平台的内幕通常会带来满足感和舒适感,深入了解也能帮助我写出更好的应用.知道 可以使用哪些工具以及他们是怎样作为整个复杂框架的一部分来互相配合的可以更容易地找出最好的解决方案,更重要的是可以在出现问题时更好的解决它们.这篇 文章的目标是从系统级别了解ASP.NET并帮助理解请求(request)是如何在ASP.NET的处理管道中流转的.同样,我们会了解核心引擎和 Web请求如何在那里结束.这些信息大部分并不是你在日常工作时必须了解的,但是它对于理解ASP.NET架构如何把请求路由到你的代码(通常是非常高层 的)中是非常有益的.

不管怎么样,ASP.NET从更低的层次上提供了更多的灵活性.HTTP运行时和请求管道在 构建WebForms和WebServices上提供了同样的能力-它们事实上都是建立在.NET托管代码上的.而且所有这些同样的功能对你也是可用的, 你可用决定你是否需要建立一个比WebForms稍低一点层次的定制的平台.

WebForms显然是最简单的构建绝大多数Web接口的方法,不过如果你是在建立自定义的 内容处理器(handler),或者有在处理输入输出内容上有特殊的要求,或者你需要为另外的应用建立一个定制的应用程序服务接口,使用这些更低级的处理 器(handler)或者模块(module)能提供更好的性能并能对实际请求处理提供更多的控制.在WebForms和WebServices这些高层 实现提供它们那些能力的同时,它们也对请求增加了一些额外负担,这些都是在更底层可以避免的.

ASP.NET是什么

让我们以一个简单的定义开始:什么是ASP.NET?我喜欢这样定义ASP.NET:

          

ASP.NET是一个复杂的使用托管代码来从头到尾处理Web请求的引擎.

它并不只是WebForms和WebServies…   

ASP.NET是一个请求处理引擎.它接收一个发送过来的请求,把它传给内部的管道直到终 点,作为一个开发人员的你可以在这里附加一些代码来处理请求.这个引擎是和HTTP/Web服务器完全分隔的.事实上,HTTP运行时是一个组件,使你可 以摆脱IIS或者任何其他的服务器程序,将你自己的程序寄宿在内.例如,你可以将ASP.NET运行时寄宿在一个Windows form程序中(查看http://www.west-wind.com/presentations/aspnetruntime/aspnetruntime.asp可以得到更加详细的信息)

运行时提供了一个复杂但同时非常优雅的在管道中路由请求的机制.其中有很多相关的对象,大多 数都是可扩展的(通过继承或者事件接口),在几乎所有的处理流程上都是如此.所以这个框架具有高度可扩展性.通过这个机制,挂接到非常底层的接口(比如缓 存,认证和授权)都变得可能了.你甚至可以在预处理或者处理后过滤内容,也可以简单的将符合特殊标记的请求直接路由你的代码或者另一个URL上.存在着许 多不同的方法来完成同一件事,但是所有这些方法都是可以简单直接地实现的,同时还提供了灵活性,可以得到最好的性能和开发的简单性.

整个ASP.NET引擎是完全建立在托管代码上的,所有的扩展功能也是通过托管代码扩展来提供的

整个ASP.NET引擎是完全建立在托管代码上的,所有的扩展功能也是通过托管代码扩展来提 供的.这是对.NET框架具有构建复杂而且高效的框架的能力的最好的证明.ASP.NET最令人印象深刻的地方是深思熟虑的设计,使得框架非常的容易使 用,又能提供挂接到请求处理的几乎所有部分的能力.

通过ASP.NET你可以从事从前属于ISAPI扩展和IIS过滤器领域的任务-有一些限 制,但是比起ASP来说是好多了.ISAPI是一个底层的Win32风格的API,有着非常粗劣的接口而且难以用来开发复杂的程序.因为ISAPI非常底 层,所以它非常的快,但是对于应用级的开发者来说是十分难以管理的.所以,ISAPI通常用来提供桥接的接口,来对其他应用或者平台进行转交.但是这并不 意味者ISAPI将消亡.事实上,ASP.NET在微软的平台上就是通过ISAPI扩展来和IIS进行交互的,这个扩展寄宿着.NET运行时和 ASP.NET运行时.ISAPI提供了核心的接口,ASP.NET使用非托管的ISAPI代码通过这个接口来从Web服务器获取请求,并发送响应回客户 端.ISAPI提供的内容可以通过通用对象(例如HttpRequest和HttpResponse)来获取,这些对象通过一个定义良好并有很好访问性的 接口来暴露非托管数据.

从浏览器到ASP.NET

让我们从一个典型的ASP.NET Web请求的生命周期的起点开始.当用户输入一个URL,点击了一个超链接或者提交了一个HTML表单(form)(一个POST请求,相对于前两者在一 般意义上都是GET请求).或者一个客户端程序可能调用了一个基于ASP.NET的WebService(同样由ASP.NET来处理).在Web服务器 端,IIS5或6,获得这个请求.在最底层,ASP.NET和IIS通过ISAPI扩展进行交互.在ASP.NET环境中这个请求通常被路由到一个扩展名 为.aspx的页面上,但是这个流程是怎么工作的完全依赖于处理特定扩展名的HTTP Handler是怎么实现的.在IIS中.aspx通过’应用程序扩展’(又称为脚本映射)被映射到ASP.NET的ISAPI扩展DLL- aspnet_isapi.dll.每一个请求都需要通过一个被注册到aspnet_isapi.dll的扩展名来触发ASP.NET(来处理这个请 求).

依赖于扩展名ASP.NET将请求路由到一个合适的处理器(handler)上,这个处理器 负责获取这个请求.例如,WebService的.asmx扩展名不会将请求路由到磁盘上的一个页面,而是一个由特殊属性(Attribute)标记为 WebService的类上.许多其他处理器和ASP.NET一起被安装,当然你也可以自定义处理器.所有这些HttpHandler在IIS中被配置为 指向ASP.NET ISAPI扩展,并在web.config(译著:ASP.NET中自带的handler是在machine.config中配置的,当然可以在 web.config中覆盖配置)被配置来将请求路由到指定的HTTP Handler上.每个handler都是一个处理特殊扩展的.NET类,可以从一个简单的只包含几行代码的Hello World类,到非常复杂的handler如ASP.NET的页面或者WebService的handler.当前,只要了解ASP.NET的映射机制是 使用扩展名来从ISAPI接收请求并将其路由到处理这个请求的handler上就可以了.

对在IIS中自定义Web请求处理来说,ISAPI是第一个也是最高效的入口

ISAPI连接

ISAPI是底层的非托管Win32 API.ISAPI定义的接口非常简单并且是为性能做了优化的.它们是非常底层的-处理指针和函数指针表来进行回调-但是它们提供了最底层和面向效率的接 口,使开发者和工具提供商可以用它来挂接到IIS上.因为ISAPI非常底层所以它并不适合来开发应用级的代码,而且ISAPI倾向于主要被用于桥接接 口,向上层工具提供应用服务器类型的功能.例如,ASP和ASP.NET都是建立在ISAPI上的,Cold Fusion,运行在IIS上的多数Perl,PHP以及JSP实现,很多第三方解决方案(如我的Wisual FoxPro的Web连接框架)都是如此.ISAPI是一个杰出的工具,可以为上层应用提供高效的管道接口,这样上层应用可以抽象出ISAPI提供的信 息.在ASP和ASP.NET中,将ISAPI接口提供的信息抽象成了类型Request和Response这样的对象,通过它们来读取ISAPI请求中 对应的信息.将ISAPI想像成管道.对ASP.NET来说,ISAPI dll是非常的”瘦”的,只是作为一个路由机制来将原始的请求转发到ASP.NET运行时.所有那些沉重的负担和处理,甚至请求线程的管理都发生在 ASP.NET引擎内部和你的代码中.

作为协议,ISAPI同时支持ISAPI扩展和ISAPI过滤器(Filter).扩展是一 个请求处理接口,提供了处理Web服务器的输入输出的逻辑-它本质上是一个处理(事物?)接口.ASP和ASP.NET都被实现为ISAPI扩展. ISAPI过滤器是挂接接口,提供了查看进入IIS的每一个请求的能力,并能修改请求的内容或者改变功能型的行为,例如认证等.顺便提一下, ASP.NET通过了两种概念映射了类似ISAPI的功能:Http Handler类似扩展,Http Module类似过滤器.我们将在后面详细讨论它们.

ISAPI是开始一个ASP.NET请求的最初的入口.ASP.NET映射了好几个扩展名到它的ISAPI扩展,此扩展位于.NET框架的目录下:

<.NET FrameworkDir>/aspnet_isapi.dll

你可以在IIS服务管理界面上看到这些映射,如图1.查看网站根目录的属性中的主目录配置页,然后查看配置|映射.

图1:IIS映射了多种扩展名如.ASPX到ASP.NET的ISAPI扩展.通过这个机制请求会在Web服务器这一层被路由到ASP.NET的处理管道.

由于.NET需要它们中的一部分,你不应该设置手动这些扩展名.使用aspnet_regiis.exe这个工具来确保所有的映射都被正确的设置了:

cd <.NetFrameworkDirectory>

aspnet_regiis – i

这个命令将为整个Web站点注册特定版本的ASP.NET运行时,包括脚本 (扩展名) 映射和客户端脚本库(包括进行控件验证的代码等).注意它注册的是<.NetFrameworkDirectory>中安装的特定版本的 CLR(如1.1,2.0).aspnet_regiis的选项令您可以对不同的虚拟目录进行配置.每个版本的.NET框架都有自己不同版本的 aspnet_regiis工具,你需要运行对应版本的aspnet_regiis来为web站点或者虚拟目录来配置指定版本的.NET框架.从 ASP.NET2.0开始提供了ASP.NET配置页面,可以通过这个页面在IIS管理控制台来交互的配置.NET版本.

IIS6通配符应用程序映射

如果你有一个ASP.NET应用程序需要处理虚拟目录的(或者是整个Web站点,如果配置为 根目录的话)每一个请求,IIS6引入了新的称为通配符应用程序映射的概念.一个映射到通配符的ISAPI扩展在每个请求到来时都会被触发,而不管扩增名 是什么.这意味着每个页面都会通过这个扩展来处理.这是一个强大的功能,你可以用这个机制来创建虚拟Url和不使用文件名的unix风格的URL.然而, 使用这个设置的时候要注意,因为它会把所有的东西都传给你的应用,包括静态htm文件,图片,样式表等等.

IIS 5 和6以不同的方式工作

当一个请求来到时,IIS检查脚本映射(扩展名映射)然后把请求路由到aspnet_isapi.dll.这个DLL的操作和请求如何进入ASP.NET运行时在IIS5和6中是不同的.图2显示了这个流程的一个粗略概览.

在IIS5中,aspnet_isapi.dll直接寄宿在inetinfo.exe进程 中,如果你设置了Web站点或虚拟目录的隔离度为中或高,则会寄宿在IIS单独的(被隔离的)工作进程中.当第一个ASP.NET请求来到,DLL (aspnet_isapi.dll)会开始另一个新进程aspnet_wp.exe并将请求路由到这个进程中来进行处理.这个进程依次加载并寄宿. NET运行时.每个转发到ISAPI DLL的请求都会通过命名管道调用被路由到这个进程来.

图2-从较高层次来看请求从IIS到ASP.NET运行时,并通过请求处理管道的流程.IIS5和IIS6通过不同的方式与ASP.NET交互,但是一旦请求来到ASP.NET管道,整个处理流程就是一样的了.

不同于以前版本的服务器,IIS6为ASP.NET做了全面的优化

IIS6-应用程序池万岁

IIS6对处理模型做了意义重大的改变,IIS不再直接寄宿象ISAPI扩展这样的外部可执 行代码.IIS总是创建一个独立的工作线程-一个应用程序池-所有的处理都发生在这个进程中,包括ISAPI dll的执行.应用程序池是IIS6的一个很大的改进,因为它允许对指定线程中将会执行什么代码进行非常细粒度的控制.应用程序池可以在每个虚拟路径上或 者整个Web站点上进行配置,这样你可以将每个Web应用隔离到它们自己的进程中,这样每个应用都将和其他运行在同一台机器上的Web应用完全隔离.如果 一个进程崩溃了,不会影响到其他进程(至少在Web处理的观点上来看是如此).

不止如此,应用程序池还是高度可配置的.你可以通过设置池的执行扮演级别 (execution impersonation level )来配置它们的运行安全环境,这使你可以定制赋予一个Web应用的权限(同样,粒度非常的细).对于ASP.NET的一个大的改进是,应用程序池覆盖了在 machine.config文件中大部分的ProcessModel节的设置.这一节的设置在IIS5中非常的难以管理,因为这些设置是全局的而且不能 在应用程序的web.config文件中被覆盖.当运行IIS6是,ProcessModel相关的设置大部分都被忽略了,取而代之的是从应用程序池中读 取.注意这里说的是大部分-有些设置,如线程池的大小还有IO线程的设置还是从machine.config中读取,因为它们在线程池的设置中没有对应 项.

因为应用程序池是外部的可执行程序,这些可执行程序可以很容易的被监控和管理.IIS6提供 了一系列的进行系统状况检查,重启和超时的选项,可以很方便的用来检查甚至在许多情况下可以修正程序的问题.最后IIS6的应用程序池并不像IIS5的隔 离模式那样依赖于COM+,这样做一来可以提高性能,二来提高了稳定性(特别对某些内部需要调用COM组件的应用来说)

尽管IIS6的应用程序池是单独的EXE,但是它们对HTTP操作进行了高度的优化,它们直 接和内核模式下的HTTP.SYS驱动程序进行通讯.收到的请求被直接路由给适当的应用程序池.InetInfo基本上只是一个管理程序和一个配置服务程 序-大部分的交互实际上是直接在HTTP.SYS和应用程序池之间发生,所有这些使IIS6成为了比IIS5更加的稳定和高效的环境.特别对静态内容和 ASP.NET程序来说这是千真万确的.

一个IIS6应用程序池对于ASP.NET有着天生的认识,ASP.NET可以在底层的API上和它进行交互,这允许直接访问HTTP缓存API,这样做可以将ASP.NET级别的缓存直接下发到Web服务器.

在IIS6中,ISAPI扩展在应用程序池的工作进程中运行. .NET运行时也在同一个进程中运行,所以ISAPI扩展和.NET运行时的通讯是发生在进程内的,这样做相比IIS5使用的命名管道有着天生的性能优 势.虽然IIS的寄宿模型有着非常大的区别,进入托管代码的接口却异常的相似-只有路由消息的过程有一点区别.

ISAPIRuntime.ProcessRequest()函数是进入ASP.NET的第一站

进入.NET运行时

进入.NET运行时的真正的入口发生在一些没有被文档记载的类和接口中(译著:当然,你可以 用Reflector来查看J).除了微软,很少人知道这些接口,微软的家伙们也并不热衷于谈论这些细节,他们认为这些实现细节对于使用ASP.NET开 发应用的开发人员并没有什么用处.

工作进程(IIS5中是ASPNET_WP.EXE,IIS6中是W3WP.EXE)寄宿. NET运行时和ISAPI DLL,它(工作进程)通过调用COM对象的一个小的非托管接口最终将调用发送到ISAPIRuntime类的一个实例上(译注:原文为an instance subclass of the ISAPIRuntime class,但是ISAPIRuntime类是一个sealed类,疑为作者笔误,或者这里的subclass并不是子类的意思).进入运行时的第一个入 口就是这个没有被文档记载的类,这个类实现了IISAPIRuntime接口(对于调用者说明来说,这个接口是一个COM接口)这个基于Iunknown 的底层COM接口是从ISAPI扩展到ASP.NET的一个预定的接口.图3展示了IISAPIRuntime接口和它的调用签名.(使用了Lutz Roeder出色的.NET Reflector 工具http://www.aisto.com/roeder/dotnet/).这是一个探索这个步步为营过程的很好的方法.

图3-如果你想深入这个接口,打开Reflector,指向 System.Web.Hosting命名空间. ISAPI DLL通过调用一个托管的COM接口来打开进入ASP.NET的入口,ASP.NET接收一个指向ISAPI ECB的非托管指针.这个ECB包含访问完整的ISAPI接口的能力,用来接收请求和发送响应回到IIS.

IISAPIRuntime接口作为从ISAPI扩展来的非托管代码和ASP.NET之间的接口点(IIS6中直接相接,IIS5中通过命名管道).如果你看一下这个类的内部,你会找到含有以下签名的ProcessRequest函数:

 [return: MarshalAs(UnmanagedType.I4)]

int ProcessRequest([In] IntPtr ecb, 

                   [In, MarshalAs(UnmanagedType.I4)] int useProcessModel);

其中的ecb参数就是ISAPI扩展控制块(Extention Control Block),被当作一个非托管资源传递给ProcessRequest函数.这个函数接过ECB后就把它做为基本的输入输出接口,和Request和 Response对象一起使用.ISAPI ECB包含有所有底层的请求信息,如服务器变量,用于表单(form)变量的输入流和用于回写数据到客户端的输出流.这一个ecb引用基本上提供了用来访 问ISAPI请求所能访问的资源的全部功能,ProcessRequest是这个资源(ecb)最初接触到托管代码的入口和出口.

ISAPI扩展异步地处理请求.在这个模式下ISAPI扩展马上将调用返回到工作进程或者 IIS线程上,但是在当前请求的生命周期上ECB会保持可用.ECB含有使ISAPI知道请求已经被处理完的机制(通过 ecb.ServerSupportFunction方法)(译注:更多信息,可以参考开发ISAPI扩展的文章),这使得ECB被释放.这个异步的处理 方法可以马上释放ISAPI工作线程,并将处理传递到由ASP.NET管理的一个单独的线程上.

ASP.NET接收到ecb引用并在内部使用它来接收当前请求的信息,如服务器变量, POST的数据,同样它也返回信息给服务器.ecb在请求完成前或超时时间到之前都保持可访问(stay alive),这样ASP.NET就可以继续和它通讯直到请求处理完成.输出被写入ISAPI输出流(使用ecb.WriteClient())然后请求 就完成了,ISAPI扩展得到请求处理完成的通知并释放ECB.这个实现是非常高效的,因为.NET类本质上只是对高效的、非托管的ISAPI ECB的一个非常”瘦”(thin)的包装器.

装载.NET-有点神秘

让我们从这儿往回退一步:我跳过了.NET运行时是怎么被载入的.这是事情变

  • 13
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值