.NET MVC5簡介(五)管道處理模型IHttpModule

来源:https://www.cnblogs.com/taotaozhuanyong/archive/2019/09/24/11581464.html
-Advertisement-
Play Games

https://www.cnblogs.com/JimmyZhang/archive/2007/09/04/880967.html IHttpModule HTTPRuntime(運行時)。在一個控制台程式中,程式的入口是Program中的Main方法。那麼,一個網站的入口在哪裡呢?在最開始的ash ...


https://www.cnblogs.com/JimmyZhang/archive/2007/09/04/880967.html

IHttpModule

HTTPRuntime(運行時)。在一個控制台程式中,程式的入口是Program中的Main方法。那麼,一個網站的入口在哪裡呢?在最開始的ashx中,有個ProcessRequest方法,後來在WebForm中,在後臺是一個不分類,繼承自Page類,在Page_Load方法中去寫代碼。其實Page類型也有一個ProcessRequest的虛方法。

 

 

 都是這個ProcessRequest方法來處理請求的。在MVC中也是如此。在MVC中,任何一個Http請求,一定有一個IHttpHandler來處理,在這個介面中,定義了一個ProcessRequest方法。HttpApplication繼承自IHttpHandler介面。任何一個Http請求就是一個HttpApplication對象來處理的,然後處理過程固定包含許可權認證、緩存處理、Session處理、Cookie出庫、生成html、輸出客戶端,與此同時,千千萬萬的開發者,又有各種各樣的擴展訴求,任何一個環節都有可能擴展,如果是我們來設計,該怎麼設計?

其實在MVC框架裡面,用到的是觀察者模式:

在HttpApplication類型,有這些事件:

 //
        // 摘要:
        //     Occurs just before ASP.NET sends HTTP headers to the client.
        public event EventHandler PreSendRequestHeaders;
 //
        // 摘要:
        //     Occurs when the handler is selected to respond to the request.
        public event EventHandler MapRequestHandler;
 //
        // 摘要:
        //     Occurs when the application is disposed.
        public event EventHandler Disposed;
 //
        // 摘要:
        //     Occurs as the first event in the HTTP pipeline chain of execution when ASP.NET
        //     responds to a request.
        public event EventHandler BeginRequest;
 //
        // 摘要:
        //     Occurs when a security module has established the identity of the user.
        public event EventHandler AuthenticateRequest;
 //
        // 摘要:
        //     Occurs when a security module has established the identity of the user.
        public event EventHandler PostAuthenticateRequest;
 //
        // 摘要:
        //     Occurs when a security module has verified user authorization.
        public event EventHandler AuthorizeRequest;
 //
        // 摘要:
        //     Occurs when the user for the current request has been authorized.
        public event EventHandler PostAuthorizeRequest;
 //
        // 摘要:
        //     Occurs when ASP.NET finishes an authorization event to let the caching modules
        //     serve requests from the cache, bypassing execution of the event handler (for
        //     example, a page or an XML Web service).
        public event EventHandler ResolveRequestCache;
 //
        // 摘要:
        //     Occurs when ASP.NET bypasses execution of the current event handler and allows
        //     a caching module to serve a request from the cache.
        public event EventHandler PostResolveRequestCache;
 //
        // 摘要:
        //     Occurs just before ASP.NET sends content to the client.
        public event EventHandler PreSendRequestContent;
 //
        // 摘要:
        //     Occurs when ASP.NET has mapped the current request to the appropriate event handler.
        public event EventHandler PostMapRequestHandler;
 //
        // 摘要:
        //     Occurs when ASP.NET has completed processing all the event handlers for the System.Web.HttpApplication.LogRequest
        //     event.
        public event EventHandler PostLogRequest;
 //
        // 摘要:
        //     Occurs when the managed objects that are associated with the request have been
        //     released.
        public event EventHandler RequestCompleted;
 //
        // 摘要:
        //     Occurs when the request state (for example, session state) that is associated
        //     with the current request has been obtained.
        public event EventHandler PostAcquireRequestState;
 //
        // 摘要:
        //     Occurs just before ASP.NET starts executing an event handler (for example, a
        //     page or an XML Web service).
        public event EventHandler PreRequestHandlerExecute;
 //
        // 摘要:
        //     Occurs when the ASP.NET event handler (for example, a page or an XML Web service)
        //     finishes execution.
        public event EventHandler PostRequestHandlerExecute;
 //
        // 摘要:
        //     Occurs after ASP.NET finishes executing all request event handlers. This event
        //     causes state modules to save the current state data.
        public event EventHandler ReleaseRequestState;
 //
        // 摘要:
        //     Occurs when ASP.NET has completed executing all request event handlers and the
        //     request state data has been stored.
        public event EventHandler PostReleaseRequestState;
 //
        // 摘要:
        //     Occurs when ASP.NET finishes executing an event handler in order to let caching
        //     modules store responses that will be used to serve subsequent requests from the
        //     cache.
        public event EventHandler UpdateRequestCache;
 //
        // 摘要:
        //     Occurs when ASP.NET finishes updating caching modules and storing responses that
        //     are used to serve subsequent requests from the cache.
        public event EventHandler PostUpdateRequestCache;
 //
        // 摘要:
        //     Occurs just before ASP.NET performs any logging for the current request.
        public event EventHandler LogRequest;
 //
        // 摘要:
        //     Occurs when ASP.NET acquires the current state (for example, session state) that
        //     is associated with the current request.
        public event EventHandler AcquireRequestState;
 //
        // 摘要:
        //     Occurs as the last event in the HTTP pipeline chain of execution when ASP.NET
        //     responds to a request.
        public event EventHandler EndRequest;
 //
        // 摘要:
        //     Occurs when an unhandled exception is thrown.
        public event EventHandler Error;
View Code

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 這裡用的是觀察者模式,把固定的步驟直接卸載handler裡面,在步驟前後分別放一個事件,然後開發者可以對事件註冊動作,等著請求進來了,然後就可以按照順訊執行一下。這種設計是不是很完美?但是仍有不完美的地方,就是每個請求都要執行這些事件,太多管閑事了。在.NET Core中出現了中間件,比這種更加完美。後續再詳細介紹。

請見下列代碼

 public class HttpProcessDemo
 {
     public class HttpApplicationDemo : IHttpHandler
     {
         public bool IsReusable => true;

         public event Action BeginRequest;
         public event Action EndRequest;
         public event Action PreSomething1Handler;
         public event Action PostSomething1Handler;
         public event Action PreSomething2Handler;
         public event Action PostSomething2Handler;
         public event Action PreSomething3Handler;
         public event Action PostSomething3Handler;
         public event Action PreSomething4Handler;
         public event Action PostSomething4Handler;
         public event Action PreSomething5Handler;
         public event Action PostSomething5Handler;
         public event Action PreSomething6Handler;
         public event Action PostSomething6Handler;
         public void ProcessRequest(HttpContext context)
         {
             this.BeginRequest?.Invoke();

             this.PreSomething1Handler?.Invoke();
             Console.WriteLine("Something 1");
             this.PostSomething1Handler?.Invoke();

             this.PreSomething2Handler?.Invoke();
             Console.WriteLine("Something 2");
             this.PostSomething2Handler?.Invoke();
             this.PreSomething3Handler?.Invoke();
             Console.WriteLine("Something 3");
             this.PostSomething3Handler?.Invoke();
             this.PreSomething4Handler?.Invoke();
             Console.WriteLine("Something 4");
             this.PostSomething4Handler?.Invoke();

             this.PreSomething5Handler?.Invoke();
             Console.WriteLine("Something 5");
             this.PostSomething5Handler?.Invoke();
             this.PreSomething6Handler?.Invoke();
             Console.WriteLine("Something 6");
             this.PostSomething6Handler?.Invoke();

             this.EndRequest?.Invoke();
         }
         //任何請求進來,只能是 123456
         //事件升級後,可以在程式啟動時,實例化HttpApplicationDemo後,可以給事件註冊動作,請求再進來時,處理不僅是123456了,還有多個事件裡面的動作
     }
View Code

對HttpApplication裡面的事件進行動作註冊,就叫IHttpModule。

自定義一個HttpModule+配置文件註冊,然後任何一個請求都會執行Init裡面註冊給Application事件的動作。

 

 

 

 public class CustomHttpModule : IHttpModule
 {
     public void Dispose()
     {
         Console.WriteLine();
     }

     public event EventHandler CustomHttpModuleHandler;

     /// <summary>
     /// 註冊動作
     /// </summary>
     /// <param name="context"></param>
     public void Init(HttpApplication application)
     {
         application.BeginRequest += (s, e) =>
           {
               this.CustomHttpModuleHandler?.Invoke(application, null);
           };
         //application.EndRequest += (s, e) =>
         //{
         //    HttpContext.Current.Response.Write("CustomHttpModule.EndRequest");
         //};
         #region 為每一個事件,都註冊了一個動作,向客戶端輸出信息
         application.AcquireRequestState += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "AcquireRequestState        "));
         application.AuthenticateRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "AuthenticateRequest        "));
         application.AuthorizeRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "AuthorizeRequest           "));
         application.BeginRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "BeginRequest               "));
         application.Disposed += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "Disposed                   "));
         application.EndRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "EndRequest                 "));
         application.Error += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "Error                      "));
         application.LogRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "LogRequest                 "));
         application.MapRequestHandler += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "MapRequestHandler          "));
         application.PostAcquireRequestState += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostAcquireRequestState    "));
         application.PostAuthenticateRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostAuthenticateRequest    "));
         application.PostAuthorizeRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostAuthorizeRequest       "));
         application.PostLogRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostLogRequest             "));
         application.PostMapRequestHandler += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostMapRequestHandler      "));
         application.PostReleaseRequestState += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostReleaseRequestState    "));
         application.PostRequestHandlerExecute += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostRequestHandlerExecute  "));
         application.PostResolveRequestCache += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostResolveRequestCache    "));
         application.PostUpdateRequestCache += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PostUpdateRequestCache     "));
         application.PreRequestHandlerExecute += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PreRequestHandlerExecute   "));
         application.PreSendRequestContent += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PreSendRequestContent      "));
         application.PreSendRequestHeaders += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "PreSendRequestHeaders      "));
         application.ReleaseRequestState += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "ReleaseRequestState        "));
         application.RequestCompleted += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "RequestCompleted           "));
         application.ResolveRequestCache += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "ResolveRequestCache        "));
         application.UpdateRequestCache += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>來自MyCustomModule 的處理,{0}請求到達 {1}</h1><hr>", DateTime.Now.ToString(), "UpdateRequestCache         "));
         #endregion
     }
 }
View Code

訪問下頁面,就是這樣的結果:

 

 

 正常流程下,會按照順序執行19個事件。

學完HttpModule,我們可以做點什麼有用的擴展?

  任何一個請求都會執行HttpModuleInit裡面註冊給Application的事件

  1、日誌-性能監控

  2、許可權

  3、緩存

  4、頁面加點東西

  5、請求過濾

  6、MVC就是一個Module的擴展

不適合的:不是針對全部請求的,就不太適合用Module,因為有性能損耗

  1、多語言,根據Cookie信息去查詢不同的數據做不同的展示,如果是全部一套處理,最後HttpModule攔截+處理,適合httpModule

  2、跳轉到不同界面,也不合適

  3、防盜鏈,針對一類的尾碼來處理的,而不是全部請求---判斷----再防盜鏈

在HttpModule裡面發佈一個CustomHttpModuleHandler,在Global增加一個動作CustomHttpModuleBingle_CustomHttpModuleHandler(配置文件module名稱_module裡面事件名稱),請求響應時,該事件會執行

protected void CustomHttpModuleBingle_CustomHttpModuleHandler(object sender, EventArgs e)
{
    this.logger.Info("this is CustomHttpModuleBingle_CustomHttpModuleHandler");
}

HttpModule是對HttpApplication的事件動作註冊動作,Global是對HttpModule裡面的事件註冊動作。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 第一步 接下來我們將看見如何在 Python 中運行一個傳統的“Hello World”程式。Python教程本章將會教你如何編寫、保存與運行 Python 程式。 通過 Python 來運行的你的程式有兩種方法——使用互動式解釋器提示符或直接運行一個源代碼文件。我們將瞭解如何使用他們二者的功能。 ...
  • 在應用中需要使用調度框架來做一些統計的功能,可惜在Windows上可用的不多,最後選擇了APScheduler這個調度器。 用法不多介紹,只總結一下在使用中遇到的坑。 app_context 問題 凡是在APScheduler中調用的function,只要用到初始化跟app相關的對象(如db,mai ...
  • 一、迴圈 輸入一個數字,輸出該數字有幾位 二、while迴圈 迴圈體內要有改變條件的機會,避免死迴圈 while迴圈的意思就是:當條件滿足時,不斷地重覆迴圈體內的語句 迴圈執行之前判斷是否繼續迴圈,所以有可能迴圈一次也沒有被執行 看我們上面的代碼,是否有點多餘的成分,我們來進行改造,但是還有一個問題 ...
  • # 深淺拷貝 1 import copy 2 3 a = ["xiaoming",111,[5000,2000]] 4 b = a 5 print("b:%s" % b) #a,b共用同一塊記憶體地址,輸出結果b:['xiaoming', 111, [5000, 2000]] 6 7 #淺拷貝只拷貝第 ...
  • 通過以下思維導圖,學習委托的基本概念,後面著重講解委托的運用,希望通過最簡單的方式收穫更多的知識。 1.委托的各種寫法 1、委托 委托名=new 委托(會調用的方法名); 委托名(參數); 2、委托 委托名 =會調用的方法名; 委托名(參數); 3、匿名方法:委托 委托名=delegate(參數){ ...
  • ASP.NET有個大佬,HttpContext(在.Net Core中依然是它)Http請求的上下文,任何一個環節都是需要HttpContext的,需要的參數信息,處理的中間結果,最終的結果,都是放在HttpContext,是一個貫穿全局的對象。 所謂的六大對象,其實就是HttpContext的屬性 ...
  • public class CEBSignClient { public void StartSignClient() { } private static SignClientConfig _signClientConfig; public static SignClientConfig CebSi ...
  • 瀏覽器到網站程式 上一篇中,介紹IHttpModule的時候,自定義一個類CustomHttpModule繼承自IHttpModule,自定義一個事件,並配合配置文件,就可以執行自定義Module中的Init方法。我們在瀏覽一個View視圖,並新建一個WebForm頁面,也瀏覽一下 我們可以看出來, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...