httpHandlers與Http處理程式

来源:http://www.cnblogs.com/HopeGi/archive/2016/09/25/5905112.html
-Advertisement-
Play Games

ASP.NET HTTP 處理程式是響應對 ASP.NET Web 應用程式的請求而運行的過程(通常稱為"終結點")。最常用的處理程式是處理 .aspx 文件的 ASP.NET 頁處理程式。用戶請求 .aspx 文件時,頁通過頁處理程式來處理請求。 ASP.NET 頁處理程式僅僅是一種類型的處理程式 ...


ASP.NET HTTP 處理程式是響應對 ASP.NET Web 應用程式的請求而運行的過程(通常稱為"終結點")。最常用的處理程式是處理 .aspx 文件的 ASP.NET 頁處理程式。用戶請求 .aspx 文件時,頁通過頁處理程式來處理請求。

ASP.NET 頁處理程式僅僅是一種類型的處理程式。ASP.NET 還包括其他幾種內置的處理程式,例如用於 .asmx 文件的 Web 服務處理程式。

如果您需要進行特殊處理(可以在應用程式中使用文件擴展名進行標識),可以創建自定義 HTTP 處理程式。例如,下麵的方案就很好地利用了自定義 HTTP 處理程式:

  • RSS 源   若要為站點創建 RSS 源,可以創建一個可發出 RSS 格式 XML 的處理程式。然後將您應用程式中的 .rss 擴展名(舉例)綁定到此自定義處理程式。當用戶向站點發送以 .rss 結尾的請求時,ASP.NET 將調用您的處理程式來處理請求。
  • 圖像伺服器   如果希望 Web 應用程式能夠提供不同大小的圖像,可以編寫一個自定義處理程式來調整圖像大小,然後將調整後的圖像作為處理程式的響應返回給用戶。

HTTP 處理程式可以訪問應用程式上下文,包括請求用戶的標識(如果已知)、應用程式狀態和會話信息等。當請求 HTTP 處理程式時,ASP.NET 將調用相應處理程式上的 ProcessRequest 方法。處理程式的 ProcessRequest 方法創建一個響應,此響應隨後發送回請求瀏覽器。就像任何頁請求那樣,響應將途經訂閱了處理程式運行後所發生事件的所有 HTTP 模塊。有關處理 Web 伺服器請求的更多信息,請參見 ASP.NET 應用程式生命周期概述

HTTP 處理程式可以是同步的也可以是非同步的。同步處理程式在完成對為其調用該處理程式的 HTTP 請求的處理後才會返回。非同步處理程式運行進程的行為與向用戶發送響應無關。當您需要啟動一個可能耗費很長時間的應用程式進程,而用戶又無需等候進程完成以便從伺服器獲取響應時,非同步處理程式非常有用。

ASP.NET 中的內置 HTTP 處理程式

ASP.NET 根據文件擴展名將 HTTP 請求映射到 HTTP 處理程式。每個 HTTP 處理程式都能夠處理應用程式中的單個 HTTP URL 或 URL 擴展名組。ASP.NET 包括幾種內置的 HTTP 處理程式,如下表所列。

處理程式

說明

ASP.NET 頁處理程式 (*.aspx)

用於所有 ASP.NET 頁的預設 HTTP 處理程式。

Web 服務處理程式 (*.asmx)

用於使用 ASP.NET 創建的 Web 服務頁的預設 HTTP 處理程式。

ASP.NET 用戶控制項處理程式 (*.ascx)

用於所有 ASP.NET 用戶控制項頁的預設 HTTP 處理程式。

跟蹤處理程式 (trace.axd)

顯示當前頁跟蹤信息的處理程式。有關詳細信息,請參見如何:使用跟蹤查看器查看 ASP.NET 跟蹤信息

如上面配置所示,.NET Framework配置中添加的Handler,實際後面還跟了一堆,不過都是同一種HttpFrobiddenHandler

創建自定義 HTTP 處理程式

若要創建一個自定義 HTTP 處理程式,可以創建一個可實現 IHttpHandler 介面的類以創建同步處理程式,或者創建一個可實現 IHttpAsyncHandler的類以創建非同步處理程式。兩種處理程式介面都要求您實現 IsReusable 屬性和 ProcessRequest 方法。IsReusable 屬性指定 IHttpHandlerFactory對象(實際調用適當處理程式的對象)是否可以將您的處理程式放置在池中,並且重新使用它們以提高性能,或是否在每次需要處理程式時都必須創建新實例。ProcessRequest 方法負責實際處理單個 HTTP 請求。

創建文件擴展名

創建一個類文件作為您的 HTTP 處理程式時,可以讓您的處理程式響應尚未在 IIS 和 ASP.NET 中映射的任何文件擴展名。例如,如果您在創建用於生成 RSS 源的 HTTP 處理程式,則可以將處理程式映射到擴展名 .rss。為了讓 ASP.NET 知道哪個處理程式將用於您的自定義文件擴展名,必須在 IIS 中將處理程式類文件的擴展名映射到 ASP.NET,並且在您的應用程式中將該擴展名映射到您的自定義處理程式。

預設情況下,ASP.NET 為自定義 HTTP 處理程式映射文件擴展名 .ashx 的方式與將擴展名 .aspx 映射到 ASP.NET 頁處理程式的方式相同。因此,如果您創建具有文件擴展名 .ashx 的 HTTP 處理程式類,該處理程式將自動註冊到 IIS 和 ASP.NET。

如果想要為您的處理程式創建自定義文件擴展名,則必須顯式將該擴展名註冊到 IIS 和 ASP.NET。不使用文件擴展名 .ashx 的好處是您的處理程式隨後可以重新用於其他擴展名映射。例如,在某個應用程式中,您的自定義處理程式可能響應以 .rss 結尾的請求,而在另一個應用程式中,您的自定義處理程式可能響應以 .feed 結尾的請求。再舉一例,您的處理程式可能映射到同一應用程式中的兩個文件擴展名,但可能基於擴展名創建兩個不同的響應。

下麵通過一個例子來演示httpHandler的建立,註冊以及效果

在App_Code中添加類ApkHandler實現介面IHttpHandler

 

namespace FastDoge.Study
{
    public class ApkHandler : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            HttpRequest Request = context.Request;
            HttpResponse Response = context.Response;
            // This handler is called whenever a file ending 
            // in .sample is requested. A file with that extension
            // does not need to exist.
            Response.Write("<html>");
            Response.Write("<body>");
            Response.Write("<h1>Hello from a synchronous custom HTTP handler.</h1>");
            Response.Write("</body>");
            Response.Write("</html>");
        }
        public bool IsReusable
        {
            // To enable pooling, return true here.
            // This keeps the handler in memory.
            get { return false; }
        }
    }
}

 

 

 

接著到Web.config中註冊Hanler,這裡對於兩個不同版本的IIS也會有出入

在 IIS 6.0 和 IIS 7.0 經典模式下運行的Web.config添加以下配置

    <httpHandlers>
      <add verb="*" path="*.apk" 
        type="FastDoge.Study.ApkHandler" />
    </httpHandlers>

 

verb指定謂詞列表可以是逗號分隔的 HTTP 謂詞列表(例如,"GET, PUT, POST"),也可以是開始腳本映射(如星號 [*] 通配符)。

path:指定路徑屬性可以包含單個 URL 路徑或簡單的通配符字元串(如 *.aspx)。

type:指定逗號分隔的類/程式集組合。ASP.NET 首先在應用程式的專用 \bin 目錄中搜索程式集 DLL,然後在系統程式集緩存中搜索程式集 DLL。

IIS7集成模式配置如下

  <system.webServer>
    <handlers>
      <add name="ApkHandler" verb="*"
        path="*.apk"
        type="FastDoge.Study.ApkHandler"
        resourceType="Unspecified" />
    </handlers>
  </system.webServer>

 

在運行後在瀏覽器中輸入一個以apk為尾碼的url

在MSDN中提到的可以在IIS中通過圖形界面註冊,這裡就不嘗試了,可參考https://msdn.microsoft.com/zh-cn/library/bb515343(v=vs.100).aspx。當然如果不在配置文件中添加,要是在HttpModule中指定,要與HttpModule耦合在一起的話就如上篇所說調用HttpContext.RemapHandler方法,如在上篇提到的MyModule類中作以下改動

        private void Application_BeginRequest(Object source,
        EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;
            context.Response.Write("<h1><font color=red>" +
                "HelloWorldModule: Beginning of Request" +
                "</font></h1><hr>");

            string filePath = context.Request.FilePath;
            string fileExtension =
                VirtualPathUtility.GetExtension(filePath);
            if (fileExtension.Equals(".apk", StringComparison.InvariantCultureIgnoreCase) &&
                 context.Request.HttpMethod.Equals("GET"))
            {
                context.RemapHandler(new ApkHandler());
            }
        }

 

去掉Web.config的配置,訪問以上URL有同樣的效果。

   

非同步 HTTP 處理程式

利用非同步 HTTP 處理程式可以啟動一個外部進程(例如對遠程伺服器的方法調用),然後繼續處理程式的處理工作,而無需等待外部進程結束。在非同步 HTTP 處理程式的處理期間,ASP.NET 將通常用於外部進程的線程放回線程池中,直到處理程式收到來自外部進程的回調。這樣可以避免阻止線程,並大幅改善了性能,因為一次所能執行的線程數量是有限的。如果許多用戶都在請求依賴於外部進程的同步 HTTP 處理程式,那麼操作系統可能很快就會用完所有線程,因為大量線程被阻止,正在等待外部進程。

創建非同步處理程式時,除了實現 IHttpAsyncHandler 介面,還必須實現 BeginProcessRequest 以啟動非同步調用來處理單個 HTTP 請求。還必須實現 EndProcessRequest 方法,以便在進程結束時運行清理代碼。

下麵則定義了一個AsyncApkHandler的非同步處理程式,在BeginProcessRequest時調用一個AsynchOperation,該類實現IAsyncResult介面,需要非同步操作的代碼在方法StartAsyncWork()中調用

 

namespace FastDoge.Study
{
    public class AsyncApkHandler : IHttpAsyncHandler
    {
        public bool IsReusable { get { return false; } }

  
        public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
        {
            context.Response.Write("<p>Begin IsThreadPoolThread is " + Thread.CurrentThread.IsThreadPoolThread + " " + DateTime.Now + "  " + Thread.CurrentThread.ManagedThreadId + "</p>\r\n");
            AsynchOperation asynch = new AsynchOperation(cb, context, extraData);
            asynch.StartAsyncWork();
            return asynch;
        }

        public void EndProcessRequest(IAsyncResult result)
        {
            if (result is AsynchOperation)
            {
                (result as AsynchOperation).Context.Response.Write("<p>End IsThreadPoolThread is " + Thread.CurrentThread.IsThreadPoolThread + "  "+DateTime.Now+"  " + Thread.CurrentThread.ManagedThreadId + "</p>\r\n");
            }
        }

        public void ProcessRequest(HttpContext context)
        {
            throw new InvalidOperationException();
        }
    }

    class AsynchOperation : IAsyncResult
    {
        private bool _completed;
        private Object _state;
        private AsyncCallback _callback;
        private HttpContext _context;

        bool IAsyncResult.IsCompleted { get { return _completed; } }
        WaitHandle IAsyncResult.AsyncWaitHandle { get { return null; } }
        Object IAsyncResult.AsyncState { get { return _state; } }
        bool IAsyncResult.CompletedSynchronously { get { return false; } }

        public HttpContext Context
        {
            get
            {
                return _context;
            }
        }

        public AsynchOperation(AsyncCallback callback, HttpContext context, Object state)
        {
            _callback = callback;
            _context = context;
            _state = state;
            _completed = false;
        }

        public void StartAsyncWork()
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(StartAsyncTask), null);
        }

        private void StartAsyncTask(Object workItemState)
        {
            Thread.Sleep(3000);
            _context.Response.Write("<p>Completion IsThreadPoolThread is " + Thread.CurrentThread.IsThreadPoolThread + "  " + DateTime.Now + " " + Thread.CurrentThread.ManagedThreadId + "</p>\r\n");

            _context.Response.Write("Hello World from Async Handler!");
            _completed = true;
            _callback(this);
        }
    }
}

 

 

配置方式如之前的方式。效果如下

   

自定義 IHttpHandlerFactory 類

IHttpHandlerFactory 類接收請求並負責向相應的 HTTP 處理程式轉發請求。您可以通過創建一個實現了 IHttpHandlerFactory 介面的類來創建自定義 HTTP 處理程式工廠。創建自定義處理程式工廠可以更好地控制對 HTTP 請求的處理,因為這樣可以基於運行時條件創建不同的處理程式。例如,使用自定義 HTTP 處理程式工廠,可以在 HTTP 請求方法為 PUT 時為某個文件類型實例化一個 HTTP 處理程式,而在該方法為 GET 時實例化另一個 HTTP 處理程式。又例如,通過使用 HTTP 處理程式工廠,可以創建有限數量的 HTTP 處理程式對象,來訪問諸如資料庫連接等昂貴或有限的資源。然後,可以在以後的請求中重用這些處理程式對象。

IHttpHandlerFactory 有兩個方法

IHttpHandler GetHandler返回實現 System.Web.IHttpHandler 介面的類的實例

void ReleaseHandler使工廠可以重用現有的處理程式實例。

下麵則定義個ApkHanlderFactory,同時在ApkHandler 輸出的內容上有稍作修改(輸出當前HttpHandler的HashCode)

 

namespace FastDoge.Study
{
    public class ApkHanlderFactory : IHttpHandlerFactory
    {
        private ApkHandler _cacheHandler;

        private ApkHandler CacheHandler
        {
            get
            {
                if (_cacheHandler == null)
                {
                    _cacheHandler = new ApkHandler();
                }
                return _cacheHandler;
            }
        }

        public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
        {
            if (context.Request.QueryString.AllKeys.Contains("IsCache") &&
                context.Request["IsCache"].ToLower().Equals("true", StringComparison.InvariantCultureIgnoreCase))
            {
                return CacheHandler;
            }
            return new ApkHandler();
        }

        public void ReleaseHandler(IHttpHandler handler)
        {
            
        }
    }
}

 

 

配置文件方面與註冊IHttpHandler基本一致,只是type特性中填寫的是實現IHttpHandlerFactory介面的類名,但是在Module中通過編碼的形式指定的方式暫時沒找到,估計需要看源碼了。

請求URL如下URL時,響應的html內容一直不變

如果去除IsCache參數時,內容則每次都在變化。

   

   

參考內容

HTTP 處理程式介紹

來自 <https://msdn.microsoft.com/zh-cn/library/ms227675(v=vs.100).aspx>

HTTP 處理程式和 HTTP 模塊概述

來自 <https://msdn.microsoft.com/zh-cn/library/bb398986(v=vs.100).aspx>


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

-Advertisement-
Play Games
更多相關文章
  • 3.打開文件視圖 4.複製release目錄下的文件到Application Folder 5.創建兩個快捷方式,一個放到DeskTop,另一個放到Program Menu. 粘貼快捷方式到DeskTop和Program Menu 6.添加卸載功能: 找到C:\Windows\System32\Ms ...
  • 原文鏈接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pattern-and-dep/ 系列目錄: Relationship in Entity Framewo ...
  • 最近使用Castle.ActiveRecord框架,網上關於多數據支持的文章很少,因此有了這篇博文的產生。 開發工具VS2015,Sql Server2008R2 新建資料庫,數據初始化腳本如下: 3.新建MVC項目ActiveRecord.Demo,新建類庫Castle.ActiveRecord. ...
  • 在C#程式中,經常會有一些耗時較長的CPU密集型運算,如果直接在 UI 線程執行這樣的運算就會出現UI不響應的問題。解決這類問題的主要途徑是使用多線程,啟動一個後臺線程,把運算操作放在這個後臺線程中完成。但是原生介面的線程操作有一些難度,如果要更進一步的去完成線程間的通信就會難上加難。 還好 .NE ...
  • datagridview編輯列時,對於類中類的屬性綁定,嘗試了一下”類名.屬性名“ 並沒有正確綁定,後又嘗試了幾次無果,只能利用Linq來解決了, 首先,datagridview要綁定的是學生類(Student),而學生類里有老師類(Teacher) 正常是這樣:datagridview.Datas ...
  • 內置對象:用於頁面之間的數據交互 為什麼要使用這麼內置對象?因為HTTP的無狀態性。 Session:在電腦中,尤其是在網路應用中,稱為“會話控制”。Session 對象存儲特定用戶會話所需的屬性及配置信息。這樣,當用戶在應用程式的 Web 頁之間跳轉時,存儲在 Session 對象中的變數將不會 ...
  • Session:在不同的瀏覽器之間傳值,像銀行之類的網站為了安全把用戶名密碼保存在session裡面。每一臺電腦訪問伺服器,都會是獨立的一套session,key值都一樣,但是內容都是不一樣的 以上所有內容,都跟cookies一樣 不一樣:1、Session的保存位置是保存在伺服器上2、Sessio ...
  • 一、深入.NET框架 1..NET框架具有兩個組件:CLR(公共語言運行時)和FCL(框架類庫),CLR是.NET框架的基礎 2.框架核心類庫: System.Collections.Generic:泛型操作 System.IO:IO流操作 System.Net:網路編程 System.Data:A ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...