<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      代碼改變世界

      MVC之前的那點事兒系列(3):HttpRuntime詳解分析(下)

      2014-05-30 08:56  湯姆大叔  閱讀(5810)  評論(4)    收藏  舉報

      文章內容

      話說,經過各種各樣復雜的我們不知道的內部處理,非托管代碼正式開始調用ISPAIRuntime的ProcessRequest方法了(ISPAIRuntime繼承了IISPAIRuntime接口,該接口可以和COM進行交互,并且暴露了ProcessRequest接口方法)。至于為什么要調用這個方法,大叔也不太清楚,找不到微軟相關的資料哦。但大叔確定該方法就是我們進入HttpRuntime的正式大門,接著看吧。

      public int ProcessRequest(IntPtr ecb, int iWRType) {
      
          IntPtr pHttpCompletion = IntPtr.Zero;
      
          if (iWRType == WORKER_REQUEST_TYPE_IN_PROC_VERSION_2) {
      
              pHttpCompletion = ecb;
      
              ecb = UnsafeNativeMethods.GetEcb(pHttpCompletion);
      
          }
      
          ISAPIWorkerRequest wr = null;
      
          try {
      
              bool useOOP = (iWRType == WORKER_REQUEST_TYPE_OOP);
      
              wr = ISAPIWorkerRequest.CreateWorkerRequest(ecb, useOOP);
      
              wr.Initialize();
      
       
      
              // check if app path matches (need to restart app domain?)
      
              String wrPath = wr.GetAppPathTranslated();
      
              String adPath = HttpRuntime.AppDomainAppPathInternal;
      
       
      
              if (adPath == null ||
      
                  StringUtil.EqualsIgnoreCase(wrPath, adPath)) { 
      
                  HttpRuntime.ProcessRequestNoDemand(wr);
      
                  return 0;
      
              }
      
              else {
      
                  // need to restart app domain
      
                  HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.PhysicalApplicationPathChanged,
      
                                                  SR.GetString(SR.Hosting_Phys_Path_Changed,
      
                                                                                  adPath,
      
                                                                                  wrPath));
      
                  return 1;
      
              }
      
          }
      
          catch(Exception e) {
      
              try {
      
                  WebBaseEvent.RaiseRuntimeError(e, this);
      
              } catch {}
      
       
      
              // Have we called HSE_REQ_DONE_WITH_SESSION?  If so, don't re-throw.
      
              if (wr != null && wr.Ecb == IntPtr.Zero) {
      
                  if (pHttpCompletion != IntPtr.Zero) {
      
                      UnsafeNativeMethods.SetDoneWithSessionCalled(pHttpCompletion);
      
                  }
      
                  // if this is a thread abort exception, cancel the abort
      
                  if (e is ThreadAbortException) {
      
                      Thread.ResetAbort();
      
                  }
      
                  // IMPORTANT: if this thread is being aborted because of an AppDomain.Unload,
      
                  // the CLR will still throw an AppDomainUnloadedException. The native caller
      
                  // must special case COR_E_APPDOMAINUNLOADED(0x80131014) and not
      
                  // call HSE_REQ_DONE_WITH_SESSION more than once.
      
                  return 0;
      
              } 
      
              // re-throw if we have not called HSE_REQ_DONE_WITH_SESSION
      
              throw;
          }
      }

       

      第一個注意到的就是該方法的IntPtr類型的參數ecb,ecb是啥?ecb是一個非托管的指針,全稱是Execution Control Block,在整個Http Request Processing過程中起著非常重要的作用,我們現在來簡單介紹一個ECB。

       

      非托管環境ISAPI對ISAPIRuntime的調用,需要傳遞一些必須的數據,比如ISAPIRuntime要獲取Server Variable的數據,獲取通過Post Mehod傳回Server的數據;以及最終將Response的內容返回給非托管環境ISAPI,然后呈現給Client用戶。一般地ISAPIRuntime不能直接調用ISAPI,所以這里就通過一個對象指針實現對其的調用,這個對象就是ECB,ECB實現了對非托管環境ISAPI的訪問。

       

      還有一點特別需要強調的是,ISAPI對ISAPIRutime的調用是異步的,也就是說ISAPI調用ISAPIRutime之后立即返回。這主要是出于Performance和Responsibility考慮的,因為ASP.NET Application天生就是一個多線程的應用,為了具有更好的響應能力,異步操作是最有效的解決方式。但是這里就會有一個問題,我們知道我們對ASP.NET 資源的調用本質上是一個Request/Response的Message Exchange Pattern,異步調用往往意味著ISAPI將Request傳遞給ISAPIRuntime,將不能得到ISAPIRuntime最終生成的Response,這顯然是不能接受的。而ECB解決了這個問題,ISAPI在調用ISAPIRutime的ProcessRequest方法時會將自己對應的ECB的指針傳給它,ISAPIRutime不但可以將最終生成的Response返回給ISAPI,還能通過ECB調用ISAPI獲得一些所需的數據。

       

      上述代碼里第2個加粗的代碼是執行ISAPIWorkerRequest的靜態方法CreateWorkerRequest從而創建ISAPIWorkerRequest對象實例,參數分別為ecb和代表WorkerRequest類型的int參數iWRType,讓我們來看看這個方法的代碼:

      internal static ISAPIWorkerRequest CreateWorkerRequest(IntPtr ecb, bool useOOP) {
       
      
          ISAPIWorkerRequest wr = null;
      
          if (useOOP) {
      
              EtwTrace.TraceEnableCheck(EtwTraceConfigType.DOWNLEVEL, IntPtr.Zero);
      
       
      
              if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_APPDOMAIN_ENTER, ecb, Thread.GetDomain().FriendlyName, null, false);
      
       
      
              wr = new ISAPIWorkerRequestOutOfProc(ecb);
      
          }
      
          else {
      
              int version = UnsafeNativeMethods.EcbGetVersion(ecb) >> 16;
      
       
      
              if (version >= 7) {
      
                  EtwTrace.TraceEnableCheck(EtwTraceConfigType.IIS7_ISAPI, ecb);
      
              }
      
              else {
      
                  EtwTrace.TraceEnableCheck(EtwTraceConfigType.DOWNLEVEL, IntPtr.Zero);
      
              }
       
      
              if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_APPDOMAIN_ENTER, ecb, Thread.GetDomain().FriendlyName, null, true);
      
       
      
              if (version >= 7) {
      
                  wr = new ISAPIWorkerRequestInProcForIIS7(ecb);
      
              }
      
              else if (version == 6) {
      
                  wr = new ISAPIWorkerRequestInProcForIIS6(ecb);
      
              }
      
              else {
      
                  wr = new ISAPIWorkerRequestInProc(ecb);
      
              }
          }
          return wr;
      }

       

      通過判斷ecb和type類型的具體內容,來決定創建什么類型的WorkerRequest(上述類型的ISPAIWorkerRequest都繼承于HttpWorkerRequest),上面的代碼可以看出對不同版本的IIS進行了不同的包裝,通過其Initialize方法來初始化一些基本的信息(比如:contentType, querystring的長度,filepath等相關信息)。

       

      OK,繼續看ProcessRequest方法的加粗代碼,激動人心的時刻來了,看到HttpRuntime.ProcessRequestNoDemand(wr)這行代碼了么?這就是真正進入了ASP.NET Runtime Pipeline的唯一入口,傳遞的參數是上面屏蔽了差異化以后的WorkerRequest對象實例。HttpRuntime.ProcessRequestNoDemand最終體現在調用ProcessRequestInternal方法上,讓我們來看看該方法都是做了什么事情。

      private void ProcessRequestInternal(HttpWorkerRequest wr) {
      
          // Construct the Context on HttpWorkerRequest, hook everything together
      
          HttpContext context;
       
      
          try {
      
              context = new HttpContext(wr, false /* initResponseWriter */);
          }
          catch {
      
              // If we fail to create the context for any reason, send back a 400 to make sure
      
              // the request is correctly closed (relates to VSUQFE3962)
      
              wr.SendStatus(400, "Bad Request");
      
              wr.SendKnownResponseHeader(HttpWorkerRequest.HeaderContentType, "text/html; charset=utf-8");
      
              byte[] body = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>");
      
              wr.SendResponseFromMemory(body, body.Length);
      
              wr.FlushResponse(true);
      
              wr.EndOfRequest();
      
              return;
      
          } 
      
          wr.SetEndOfSendNotification(_asyncEndOfSendCallback, context); 
      
          // Count active requests
      
          Interlocked.Increment(ref _activeRequestCount);
      
          HostingEnvironment.IncrementBusyCount();
       
      
          try {
              // First request initialization
              try {
                  EnsureFirstRequestInit(context);
              }
              catch {
                  // If we are handling a DEBUG request, ignore the FirstRequestInit exception.
                  // This allows the HttpDebugHandler to execute, and lets the debugger attach to
                  // the process (VSWhidbey 358135)
                  if (!context.Request.IsDebuggingRequest) {
                      throw;
                  }
              } 
      
              // Init response writer (after we have config in first request init)
              // no need for impersonation as it is handled in config system
              context.Response.InitResponseWriter(); 
      
              // Get application instance
              IHttpHandler app = HttpApplicationFactory.GetApplicationInstance(context);
      
              if (app == null)
                  throw new HttpException(SR.GetString(SR.Unable_create_app_object));
      
               if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, context.WorkerRequest, app.GetType().FullName, "Start");
      
      
              if (app is IHttpAsyncHandler) {
                  // asynchronous handler
      
                  IHttpAsyncHandler asyncHandler = (IHttpAsyncHandler)app;
                  context.AsyncAppHandler = asyncHandler;
                  asyncHandler.BeginProcessRequest(context, _handlerCompletionCallback, context);
              }
              else {
                  // synchronous handler
                  app.ProcessRequest(context);
                  FinishRequest(context.WorkerRequest, context, null);
              }
          }
          catch (Exception e) {
              context.Response.InitResponseWriter();
              FinishRequest(wr, context, e);
          }
      }

       

      首先映入眼簾的是try/catch里的HttpContext對象的實例化代碼,這就是我們期待已久的全局HttpContext對象產生的地方,參數依然是WorkerRequest的實例,HttpContext構造函數代碼如下:

      // ctor used in HttpRuntime
      
      internal HttpContext(HttpWorkerRequest wr, bool initResponseWriter) {
      
          _wr = wr;
      
          Init(new HttpRequest(wr, this), new HttpResponse(wr, this)); 
      
          if (initResponseWriter)
              _response.InitResponseWriter(); 
      
          PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_EXECUTING);
      }

       

      我們又看到了2個驚喜的代碼,HttpRequest和HttpResponse的實例化,通過對WorkerRequest和對HttpContext對象this參數的傳遞,將獲取各自需要的信息,具體內部是怎么判斷操作賦值的,我們就不仔細看了,另外再花2秒鐘看一下,catch里面的代碼,有我們經常看到的Bad Request頁面顯示的HTML代碼組裝邏輯,也就是說如果HttpContext對象創建失敗的話,就會給我們顯示Bad Request頁面。

       

      我們繼續更重要的代碼,這又是另外一個入口,讓我們進入我們熟悉的HttpApplication,代碼如下:

      // Get application instance
      
      IHttpHandler app = HttpApplicationFactory.GetApplicationInstance(context);

       

      通過HttpApplicationFactory的GetApplicationInstance靜態方法,獲取我們熟悉的HttpApplication對象實例,由于HttpApplication對象是繼承IHttpAsyncHandler,而IHttpAsyncHandler又繼承于IHttpHandler,所以上面app的類型是IHttpHandler是沒有錯的。繼續看后面的if (app is IHttpAsyncHandler)代碼,就知道了app肯定走這里的分支,然后執行調用asyncHandler.BeginProcessRequest方法了。

       

      至此,HttpRuntime已經正式發揮其無可替代的作用了,也正式通過此對象正式進入了HttpApplication對象的創建以及大家熟知的HttpApplication以后的生命周期了。

      參考資料:

      http://www.ixwebhosting.mobi/asp-net-process-model-of-the-two-asp-net-http-runtime-pipeline-the-articles/

      http://dotnetslackers.com/articles/iis/ASPNETInternalsIISAndTheProcessModel2.aspx

      http://msdn.microsoft.com/en-us/library/bb470252.aspx

      http://msdn.microsoft.com/en-us/library/Aa479328.aspx 

      http://learn.iis.net/page.aspx/101/introduction-to-iis-architecture/

      http://www.rzrgm.cn/zhaoyang/archive/2011/11/16/2251200.html

      http://www.dotnetfunda.com/articles/article821-beginners-guide-how-iis-process-aspnet-request.aspx

      同步與推薦

      本文已同步至目錄索引:MVC之前的那點事兒系列

      MVC之前的那點事兒系列文章,包括了原創,翻譯,轉載等各類型的文章,如果對你有用,請推薦支持一把,給大叔寫作的動力。

      主站蜘蛛池模板: 日韩一卡二卡三卡四卡五卡| 欧美国产日韩久久mv| 97超级碰碰碰碰久久久久| 国产精品国产亚洲看不卡| 九九热精品在线观看视频| 亚洲伊人久久精品影院| 成人精品视频一区二区三区| 国产精品永久免费无遮挡| 亚洲v国产v天堂a无码二区| 日韩亚洲视频一区二区三区| 成人福利一区二区视频在线 | 曰韩无码二三区中文字幕| 扒开粉嫩的小缝隙喷白浆视频| 夜夜夜高潮夜夜爽夜夜爰爰| 人人妻人人澡人人爽不卡视频| 枝江市| 欧美人与动交视频在线观看| 国产乱子伦视频在线播放 | 国产狂喷潮在线观看| 国产系列高清精品第一页| 国产午夜福利小视频合集| 杂多县| 国产日产亚洲系列av| 制服丝袜美腿一区二区| 亚洲av午夜成人片| 国产精品天天看天天狠| 777米奇色狠狠俺去啦| 精品少妇av蜜臀av| JIZZJIZZ国产| 亚洲国产成人字幕久久| 国产欧美日韩亚洲一区二区三区| 亚洲国产精品日韩AV专区| 永久免费AV无码国产网站| 宁晋县| 国产jlzzjlzz视频免费看| 欧美综合婷婷欧美综合五月| 国内精品伊人久久久久777| 视频一区二区不中文字幕| 国产美女MM131爽爽爽| 麻豆国产传媒精品视频| 在线看av一区二区三区|