ASP.NET WebAPI框架解析第二篇(HttpModule的創建和使用)

来源:https://www.cnblogs.com/hkfyf/archive/2020/03/15/12495182.html
-Advertisement-
Play Games

我們先看一下執行流程圖圖中畫紅圈的部分便是HttpModule,在說創建HttpModule之前,先說一下HttpApplication對象,HttpApplication對象由Asp.net框架創建,每個請求對應一個HttpApplcation實例對象,Asp.Net框架內部維護了一個HttpAp... ...


我們先看一下執行流程圖

image

圖中畫紅圈的部分便是HttpModule,在說創建HttpModule之前,先說一下HttpApplication對象,HttpApplication對象由Asp.net框架創建,每個請求對應一個HttpApplcation實例對象,Asp.Net框架內部維護了一個HttpApplication對象池,可以復用該對象,以便節省伺服器資源。HttpApplication對象內部有許多事件,其中的一些事件如下:

BeginRequest Asp.net處理的第一個事件,表示處理的開始

AuthenticateRequest 驗證請求,一般用來取得請求用戶的信息

PostResolveRequestCache 已經完成緩存的獲取操作

……

EndRequest 本次請求處理完成

其中PostResolveRequestCache 這個事件就被路由模塊監聽了。我們看看一個標準HttpModule模塊的介面定義是怎麼樣的。

public interface IHttpModule
{
     void Init(HttpApplication context);

    void Dispose();

}

註意到Init(HttpApplication context)這個方法,每註冊一個HttpModule模塊,Asp.Net框架內部通過反射獲取對應的程式集,並通過反射調用Init方法,Context參數便是處理一個Http請求的HttpApplication實例對象。那怎麼讓我們註冊的模塊參與到處理Http請求中呢?前面提到HttpApplication內部有許多事件,而我們的HttpModule中的Init方法會被Asp.Net框架調用,所以我們可以利用這個去註冊相應的事件,執行我們的代碼,我們在這裡可以做很多事,比如自定義驗證、自定義授權,圖片壓縮,圖片加水印,伺服器日誌記錄、惡意請求攔截等等。

為了演示自定義HttpModule的使用,我們創建一個寄宿模式為WebHost的WebAPI,為了便於理解ASP.NET WebAPI的組成,我們不直接創建一個WebAPI模板的項目。

1.使用VS2017創建一個空的解決方案

image


2.新建一個空的.NetFramwork類庫項目和一個空的ASP.NET Web應用

image

image

image

我們對WebAPI類庫項目引用WebAPI所需的System.Web.Http.dll。我在I:\Program Files (x86)\Microsoft Visual Studio\Shared\Packages\Microsoft.AspNet.WebApi.Core.5.2.7\lib\net45路徑下找到了該dll。

image

然後在WebAPI項目下建立一個類,使用命名空間System.Web.Htpp,繼承該命名空間下的ApiController即可,然後定義一個方法,我定義的如下。註意類名一定要以Controller結尾,否則在路由匹配成功後,WebAPI框架內部不能通過路由解析到的值去反射構建對應的控制器實例對象。

image

然後對WebHost項目引用如下dll(我都是在I:\Program Files (x86)\Microsoft Visual Studio\Shared\Packages\目錄下找到的,實在找不到就創建一個WEBAPI模板然後到項目目錄下的Package文件中去拷貝)

System.Web.Http.dll

System.Web.Http.WebHost.dll

System.Net.Http.Formatting.dll

WebHost項目還要保持對WebAPI項目的引用

為WebHost項目添加Global.asax文件,VS為我們自動創建了一個Global類,並繼承於System.Web命名空間下的HttpApplication類。這個類就是處理Http請求的類。我們也可以在這裡監聽相應的事件,監聽函數格式以XXX_XXX的形式定義,至於為什麼要這麼定義的原因是為了便於通過反射進行註冊。有些事件只能在這裡監聽,比如Application_Start,Application_Start在整個應用生命周期中只會執行一次,相當於靜態構造函數.我們在Application_Start中去註冊全局的路由表,在WebHost模式下,WebAPI的路由系統實際上由ASP.NET的路由系統完成的,當然WebAPI本身的路由系統也可以完成。我們註冊以下路由表。

protected void Application_Start(object sender, EventArgs e)
{
     GlobalConfiguration.Configuration.Routes.MapHttpRoute(name: "first",routeTemplate: "webapi/{controller}/{action}");

}

然後在VS2017環境下使用IIS Express啟動,然後在瀏覽器輸入http://localhost:63210/webapi/home/index,註意在我這裡埠號是63210。便可得到如下結果。

image

我們回顧一下這個流程。

->客戶端(在這裡是瀏覽器)發起HTTP請求

->IIS Express接收到該請求

->IIS Express發現該請求路徑不是已知的靜態資源類型,進而把請求交給Asp.Net托管代碼處理

->Asp.Net從HttpApplication池中取一個實例對象去處理該Http請求

->註冊相應HttpModule模塊,並調用Init()函數,這個時候HttpContext還沒有形成,我們只能在這裡註冊相應的監聽事件函數。

->HttpContext形成,HttpApplication實例對象內部的事件輪流觸發,其中有一個PostMapRequestHandler事件,在這個事件觸發後,會調用相應HttpHandler執行相應的處理,後面再說HttpHandler

->必要的事件觸發完成之後生成Http報文並交由IIS Express返回給客戶端

->客戶端接受Http報文並解析顯示在客戶端中。

這隻是一個大概的過程,具體比這複雜,但我們關註點在HttpModule上,所以足夠了。

我們現在嘗試自己創建HttpModule

我在WebHost項目下建立了一個文件夾,然後新建了一個AuthorizeHttpModule,模擬授權,功能很簡單,看Http請求頭中是否包含name欄位,並且值為HK,否則,向Http響應報文中的Body部分寫入內容,並攔截請求。

image

namespace WebHost.HttpModules
{
     public class AuthorizeHttpModule : IHttpModule
     {
         public void Dispose()
         {
             return;
         }

        public void Init(HttpApplication context)
         {
             //此時HttpContext還未構建完成,不能在這裡操作HttpContext
             //註冊事件監聽函數
             context.BeginRequest += Authorize;
         }
         private void Authorize(object sender,EventArgs e)
         {
             HttpApplication app = sender as HttpApplication;

            if (app.Request.Headers.Get("name") != "HK")
             {
                 //不加這一行客戶端可能不能自動正確的解析字元編碼
                 app.Response.Headers.Add("content-Type", "text/html;charset=utf-8");
                 //通過Write(string s)寫入的字元串在內部預設被轉換為utf-8編碼。C#string預設編碼為UTF-16
                 //要先寫入原始的字元串編碼,調用BinaryWrite(byte[] bytes)
                 app.Response.Write("驗證不通過!");
                 app.CompleteRequest();
             }
         }
     }
}

在WebHost項目目錄下的Web.Config中配置HttpModule信息,以便Asp.Net框架讀取。註意,有個全局的Web.Config文件,其中預設註冊了許多HttpModule,其中有一個HttpModule(WebDAVModule)會截斷Put和Delete請求。

image

如上,我添加了system.webServer節點(IIS集成模式下是這樣配置,經典模式自行搜索),併在子節點modules下添加了自定義的HttpModule,其中name是HttpModule名稱,ASP.NET內部會以這個名稱作為Key,type表示HttpModule的類型名,以便反射讀取相應的類型對象。該類型所在的程式集必須在Web應用程式的Bin目錄,否則不能正常載入,由於我創建的HttpMudle是在WebHost項目中,所以不會出現問題。我們現在啟動IIS Express看看效果。

image

可以看到我們的HttpModule起作用了。我們用PostMan為請求頭添加一個欄位name,值為HK,然後請求/webapi/home/index試試看

image

可以看到沒有被攔截。前面我們提到了一個HttpHandler,這個HttpHandler實際上是最終處理頁面的處理者,後面再說。


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

-Advertisement-
Play Games
更多相關文章
  • 前言 我們一般可以在Linux伺服器上執行 命令來運行我們的.net Core WebApi應用。但是這樣運行起來的應用很不穩定,關閉終端視窗之後,應用也會停止運行。為了讓其可以穩定運行,我們需要讓它變成系統的守護進程,成為一種服務一直在系統中運行,出現異常時也能重新啟動。 Linux系統有自己的守 ...
  • 前言 在探究地球內部的結構中,如何做到在地球錶面不用深入地球內部就可以知道內部的構造呢?其實,向地球發射“地震波”。利用這種方式,可以判斷地球放回的情況,大體上,我們也可以斷定地球內部的構造了。 從這個例子中,通過一個對象的外部去瞭解對象內部的構造,都是利用了波的反射功能。而利用這種原理,在編程程式 ...
  • 目 錄 1. 概述... 2 2. iNeuOS平臺演示... 2 3. 設備驅動管理... 2 4. 服務驅動管理... 3 5. 雲組態自定義畫布... 4 6. 快速切換組態頁面菜單... 5 7. 自定義右鍵菜單項,顯示組態子頁面... 5 8. 工況關聯數據點... 6 9. 修改用戶密碼 ...
  • 本次是在原有ApiTemplate項目之上,增加一個用戶登錄許可權控制模塊,用於驗證ApiTemplate項目在面對一些簡單問題時,如何抽象並支持未來的擴展。用戶登錄許可權控制模塊看上去很簡單,但由於業餘時間總是有限的。所以藉助此機會實踐一次用戶敏捷開發。首先拆分模塊,本次只實現用戶登錄和登出。apit ...
  • 棄元就是使用下劃線_作為一個占位符,但不占存儲空間。 元組(ValueTuple、Tuple)使用棄元例子。 using System; namespace ConsoleApp4 { class Program { public static void Main() { // ValueTuple ...
  • 這篇文章是為了梳理自己關於委托的知識脈落,便於對委托有更清晰的認識。 本文的重點不在於,委托是什麼,怎麼定義委托,委托有什麼好處。。。這些網上知識很豐富了。 本文演示的是 委托是怎麼一步步形成並精簡代碼的 我稱之為“進化”。 這些方法也是從.net 1.0 2.0 3.0版本一步步形成的。 ...
  • WPF 項目遷移到.Net Core中時居然出了一堆問題...(很無語) 今天在使用的時候居然發現Process.Start居然打不開Url鏈接了? 報 找不到指定文件 的異常?! 一、bug重現 首先以.Net Core 3.1框架 中一個Console項目 打開百度為例: 運行然後你就會得到: ...
  • 在本文中,我將講解如何通過自定義 ,以便在中間件管道中發生錯誤時創建自定義響應,而不是提供一個“重新執行”管道的路徑。 作者:依樂祝 譯文:https://www.cnblogs.com/yilezhu/p/12497937.html 原文:https://andrewlock.net/creati ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...