Asp.Net请求处理机制中IsApiRuntime解析
今天看了web请求的生命周期,看完了还有些不懂,就是用反编译工具,查看封装内库的内部实现。

从计算机内部查到web.dll,使用反编译工具打开

打开后
public int ProcessRequest(IntPtr ecb, int iWRType)
{
IntPtr intPtr = IntPtr.Zero;
if (iWRType == )
{
intPtr = ecb;
ecb = UnsafeNativeMethods.GetEcb(intPtr);
}
//首先创建ISAPIWorkerRequest,将请求报文封装在内,调用CreateWorkerRequest方法来实现,
ISAPIWorkerRequest iSAPIWorkerRequest = null;
int result;
try
{
bool useOOP = iWRType == ;
iSAPIWorkerRequest = ISAPIWorkerRequest.CreateWorkerRequest(ecb, useOOP);
iSAPIWorkerRequest.Initialize();
string appPathTranslated = iSAPIWorkerRequest.GetAppPathTranslated();
string appDomainAppPathInternal = HttpRuntime.AppDomainAppPathInternal;
if (appDomainAppPathInternal == null || StringUtil.EqualsIgnoreCase(appPathTranslated, appDomainAppPathInternal))
{
//调用ProcessRequestNoDemand方法,并将封装的请求报文传入进去
HttpRuntime.ProcessRequestNoDemand(iSAPIWorkerRequest);
result = ;
}
else
{
HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.PhysicalApplicationPathChanged, SR.GetString("Hosting_Phys_Path_Changed", new object[]
{
appDomainAppPathInternal,
appPathTranslated
}));
result = ;
}
}
catch (Exception ex)
{
try
{
WebBaseEvent.RaiseRuntimeError(ex, this);
}
catch
{
}
if (iSAPIWorkerRequest == null || !(iSAPIWorkerRequest.Ecb == IntPtr.Zero))
{
throw;
}
if (intPtr != IntPtr.Zero)
{
UnsafeNativeMethods.SetDoneWithSessionCalled(intPtr);
}
if (ex is ThreadAbortException)
{
Thread.ResetAbort();
}
result = ;
}
return result;
}
在CreateWorkerRequest内部,根据不同的IIS版本创建不同的对象 // System.Web.Hosting.ISAPIWorkerRequest internal static ISAPIWorkerRequest CreateWorkerRequest(IntPtr ecb, bool useOOP)
{
ISAPIWorkerRequest result;
if (useOOP)
{
EtwTrace.TraceEnableCheck(EtwTraceConfigType.DOWNLEVEL, IntPtr.Zero);
if (EtwTrace.IsTraceEnabled(, ))
{
EtwTrace.Trace(EtwTraceType.ETW_TYPE_APPDOMAIN_ENTER, ecb, Thread.GetDomain().FriendlyName, null, false);
}
result = new ISAPIWorkerRequestOutOfProc(ecb);
}
else
{
int num = UnsafeNativeMethods.EcbGetVersion(ecb) >> ;
if (num >= )
{
EtwTrace.TraceEnableCheck(EtwTraceConfigType.IIS7_ISAPI, ecb);
}
else
{
EtwTrace.TraceEnableCheck(EtwTraceConfigType.DOWNLEVEL, IntPtr.Zero);
}
if (EtwTrace.IsTraceEnabled(, ))
{
EtwTrace.Trace(EtwTraceType.ETW_TYPE_APPDOMAIN_ENTER, ecb, Thread.GetDomain().FriendlyName, null, true);
}
if (num >= )
{
result = new ISAPIWorkerRequestInProcForIIS7(ecb);
}
else
{
if (num == )
{
result = new ISAPIWorkerRequestInProcForIIS6(ecb);
}
else
{
result = new ISAPIWorkerRequestInProc(ecb);
}
}
}
return result;
}
进入ProcessRequestNoDemand内部
// System.Web.HttpRuntime
internal static void ProcessRequestNoDemand(HttpWorkerRequest wr)
{
RequestQueue requestQueue = HttpRuntime._theRuntime._requestQueue;
wr.UpdateInitialCounters();
if (requestQueue != null)
{
wr = requestQueue.GetRequestToExecute(wr);
}
if (wr != null)
{
HttpRuntime.CalculateWaitTimeAndUpdatePerfCounter(wr);
wr.ResetStartTime();
//调用ProcessRequestNow方法,并将封装的请求报文传入
HttpRuntime.ProcessRequestNow(wr);
}
}
// System.Web.HttpRuntime
internal static void ProcessRequestNow(HttpWorkerRequest wr)
{
HttpRuntime._theRuntime.ProcessRequestInternal(wr);
}
进入ProcessRequestInternal方法内部
// System.Web.HttpRuntime
private void ProcessRequestInternal(HttpWorkerRequest wr)
{
Interlocked.Increment(ref this._activeRequestCount);
if (this._disposingHttpRuntime)
{
try
{
wr.SendStatus(, "Server Too Busy");
wr.SendKnownResponseHeader(, "text/html; charset=utf-8");
byte[] bytes = Encoding.ASCII.GetBytes("<html><body>Server Too Busy</body></html>");
byte[] expr_45 = bytes;
wr.SendResponseFromMemory(expr_45, expr_45.Length);
wr.FlushResponse(true);
wr.EndOfRequest();
}
finally
{
Interlocked.Decrement(ref this._activeRequestCount);
}
return;
}
HttpContext httpContext;
try
{
//根据请求报文创建HttpContext对象,如果创建出错误就会返回404
httpContext = new HttpContext(wr, false);
}
catch
{
try
{
wr.SendStatus(, "Bad Request");
wr.SendKnownResponseHeader(, "text/html; charset=utf-8");
byte[] bytes2 = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>");
byte[] expr_A5 = bytes2;
wr.SendResponseFromMemory(expr_A5, expr_A5.Length);
wr.FlushResponse(true);
wr.EndOfRequest();
return;
}
finally
{
Interlocked.Decrement(ref this._activeRequestCount);
}
}
wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, httpContext);
HostingEnvironment.IncrementBusyCount();
try
{
try
{
//将第一次请求设置为false
this.EnsureFirstRequestInit(httpContext);
}
catch
{
if (!httpContext.Request.IsDebuggingRequest)
{
throw;
}
}
//初始化Response
httpContext.Response.InitResponseWriter();
//根据HttpApplicationFactory创建Application实例
IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(httpContext);
if (applicationInstance == null)
{
throw new HttpException(SR.GetString("Unable_create_app_object"));
}
if (EtwTrace.IsTraceEnabled(, ))
{
EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, httpContext.WorkerRequest, applicationInstance.GetType().FullName, "Start");
}
if (applicationInstance is IHttpAsyncHandler)
{
IHttpAsyncHandler httpAsyncHandler = (IHttpAsyncHandler)applicationInstance;
httpContext.AsyncAppHandler = httpAsyncHandler;
httpAsyncHandler.BeginProcessRequest(httpContext, this._handlerCompletionCallback, httpContext);
}
else
{
applicationInstance.ProcessRequest(httpContext);
this.FinishRequest(httpContext.WorkerRequest, httpContext, null);
}
}
catch (Exception e)
{
httpContext.Response.InitResponseWriter();
this.FinishRequest(wr, httpContext, e);
}
}
//进入EnsureFirstRequestInit
// System.Web.HttpRuntime
private void EnsureFirstRequestInit(HttpContext context)
{
if (this._beforeFirstRequest)
{
bool flag = false;
try
{
Monitor.Enter(this, ref flag);
if (this._beforeFirstRequest)
{ //设置第一次请求为false
this._firstRequestStartTime = DateTime.UtcNow;
this.FirstRequestInit(context);
this._beforeFirstRequest = false;
context.FirstRequest = true;
}
}
finally
{
if (flag)
{
Monitor.Exit(this);
}
}
}
}
Application中有26个方法,从上到下有19个请求管道事件

1.熟悉请求管道实现程序运行的全过程:
(1):BeginRequest: 开始处理请求。当ASP.NET运行时接收到新的HTTP请求的时候引发这个事件
(2):AuthenticateRequest授权验证请求,获取用户授权信息。当ASP.NET 运行时准备验证用户身份的时候引发这个事件
(3):PostAuthenticateRequest获取成功
(4): AunthorizeRequest 授权,一般来检查用户是否获得权限。当ASP.NET运行时准备授权用户访问资源的时候引发这个事件
(5):PostAuthorizeRequest:获得授权
(6):ResolveRequestCache:获取页面缓存结果
(7):PostResolveRequestCache 已获取缓存
(8):PostMapRequestHandler 创建页面对象
(9):AcquireRequestState 获取Session-----先判断当前页面对象是否实现了IRequiresSessionState接口,如果实现了,则从浏览器发来的请求报文体中获得SessionID,并到服务器的Session池中获得对应的Session对象,最后赋值给HttpContext的Session属性
(10)PostAcquireRequestState 获得Session
(11)PreRequestHandlerExecute:准备执行页面对象执行页面对象的ProcessRequest方法。在ASP.NET开始执行HTTP请求的处理程序之前引发这个事件。在这个事件之后,ASP.NET 把该请求转发给适当的HTTP处理程序。
(12)PostRequestHandlerExecute 执行完页面对象了。在HTTP处理程序结束执行的时候引发这个事件
(13)ReleaseRequestState 释放请求状态
(14)PostReleaseRequestState 已释放请求状态
(15)UpdateRequestCache 更新缓存
(16)PostUpdateRequestCache 已更新缓存
(17)LogRequest 日志记录
(18)PostLogRequest 已完成日志
(19)EndRequest 完成。把响应内容发送到客户端之前引发这个事件。
转载一篇比较详细的生命周期文章:http://www.cnblogs.com/Cwj-XFH/p/6752177.html
Asp.Net请求处理机制中IsApiRuntime解析的更多相关文章
- 从Nginx的Web请求处理机制中剖析多进程、多线程、异步IO
Nginx服务器web请求处理机制 从设计架构来说,Nginx服务器是与众不同的.不同之处一方面体现在它的模块化设计,另一方面,也是最重要的一方面,体现在它对客户端请求的处理机制上. Web服务器和客 ...
- asp.net请求响应模型原理随记回顾
asp.net请求响应模型原理随记回顾: 根据一崇敬的讲师总结:(会存在些错误,大家可以做参考) 1.-当在浏览器输入url后,客户端会将请求根据http协议封装成为http请求报文.并通过主sock ...
- Asp.Net请求响应过程
Asp.Net请求响应过程 在之前,我们写了自己的Asp.Net框架,对整个流程有了一个大概的认识.这次我们来看一下Asp.Net整个请求处理过程是怎么样的. 浏览器封装请求报文,发送请求到达服务器, ...
- [译] ASP.NET 生命周期 – ASP.NET 请求生命周期(二)
ASP.NET 请求生命周期 全局应用类也可以用来跟踪每个独立请求的生命周期,包括请求从 ASP.NET 平台传递到 MVC 框架.ASP.NET 框架会创建一个定义在 Global.asax 文件中 ...
- NET/ASP.NET Routing路由(深入解析路由系统架构原理)(转载)
NET/ASP.NET Routing路由(深入解析路由系统架构原理) 阅读目录: 1.开篇介绍 2.ASP.NET Routing 路由对象模型的位置 3.ASP.NET Routing 路由对象模 ...
- ASP.Net请求小周期
另一篇另篇2 ASP.NET请求处理全过程 一个ASP.NET请求过程中,从浏览器中发出一个Web请求 到 这个请求被响应并显示在浏览器中的过程中究竟会发生哪些不同的事件,当我们进入这个事件之旅时,我 ...
- ASP.NET请求过程-从源码角度研究MVC路由、Handler、控制器
路由常用对象 RouteBase 用作表示 ASP.NET 路由的所有类的基类. 就是路由的一个基础抽象类. // // 摘要: // 用作表示 ASP.NET 路由的所有类的基类. [ ...
- ASP.NET请求过程-Handler
什么事Handler asp.net程序所有的请求都是handler处理的.以前的webform我们访问的地址是xxxxx.aspx地址,其实他也会到一个handler(我们写的业务代码都在handl ...
- 【深入ASP.NET原理系列】--ASP.NET请求管道、应用程序生命周期、整体运行机制
微软的程序设计和相应的IDE做的很棒,让人很快就能有生产力..NET上手容易,生产力很高,但对于一个不是那么勤奋的人,他很可能就不再进步了,没有想深入下去的动力,他不用去理解整个框架和环境是怎么执行的 ...
随机推荐
- C++ 矩阵乘法
//构造矩阵类,重载乘法操作符 //作者:nuaazdh //时间:2011年12月1日 #include <iostream> using namespace std; //Matrix ...
- Unity大中华区主办 第二届Unity 游戏及应用大赛 实力派精品手游盘点
Unity是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏.建筑可视化.实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎.包含如今时 ...
- CodeSmith exclude global 文件和文件夹问题 与 输入中文显示乱码问题
1.打开C:/Documents and Settings/你的用户名/Application Data/CodeSmith/v4.1/CodeSmithGui.config文件. 2.在<te ...
- javascript原型链继承
一.关于javascript原型的基本概念: prototype属性:每个函数都一个prototype属性,这个属性指向函数的原型对象.原型对象主要用于共享实例中所包含的的属性和方法. constru ...
- Linux学习之/etc/init.d/functions详解
转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=28773997&id=3996557 /etc/init.d/f ...
- 通过OCI 处理 Oracle 10g 中处理Clob大字段写入
Oracle数据库中, 通过存储过程写入Clob字段 , 当数据大于4k时, 报错 ORA-01460: 转换请求无法实施或不合理 经过排查, 数据Bind方式不对, 不能采用字符串的Bind方式 原 ...
- python打包成.exe工具py2exe0-----No such file or directory错误
转自:http://justcoding.iteye.com/blog/900993 一.简介 py2exe是一个将python脚本转换成windows上的可独立执行的可执行程序(*.exe)的工具, ...
- Flink资料(1)-- Flink基础概念(Basic Concept)
Flink基础概念 本文描述Flink的基础概念,翻译自https://ci.apache.org/projects/flink/flink-docs-release-1.0/concepts/con ...
- sim卡中的汉字存储格式
Sim卡中的ucs2格式 Sim卡中的中文都是以ucs2格式存储的,ucs2和unicode只是字节序不同,unicode是小头在前,ucs2是大头在前. Ucs2与GB2312互换可以用VC中的Wi ...
- delphi程序设计之底层原理
虽然用delphi也有7,8年了,但大部分时间还是用在系统的架构上,对delphi底层还是一知半解,今天在网上看到一篇文章写得很好,虽然是07年的,但仍有借鉴的价值. 现摘录如下: Delphi程序设 ...