The Will Will Web | 介紹一個 ASP.NET 裡鮮為人知的 Response.Filter 屬性

The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

介紹一個 ASP.NET 裡鮮為人知的 Response.Filter 屬性

ASP.NET 有一個鮮為人知也很少人使用的 Response.Filter 屬性,Response.Filter 屬性本身是一個 Stream 型別,所以可以利用 Stream 的特性,將 Response.Filter 傳給下一個 Stream 進行資料處理。換句話說,你就可以透過繼承自 Stream 的自訂型別去修改 Response.Filter 傳入的資料,並且將資料進行修正動作。

之前很早就知道有這個屬性存在,但一直沒時間研究,今天趁假日把玩了一下,感覺還不賴,發現運用這個開發技巧可發揮的領域可多了,為了讓各位有點感覺,我先秀幾段程式碼展示威力:

Response.Filter = new GZipStream(Response.Filter, CompressionMode.Compress);    
Response.AppendHeader("Content-Encoding", "gzip");

以上程式碼可以放在 Page_Init 事件裡,最主要的功能就在於他將 Response.Filter 屬性先傳入一個 GZipStream 類別中,讓所有頁面輸出的 Stream 都會經過 GZipStream 壓縮,最後再新增一個回應標頭,告知瀏覽器此頁回應的資料是透過 gzip 壓縮過的。

另外,如果你要將每個輸出的頁面自動將多餘的空白濾掉,也可以運用 Response.Filter 的技巧,有興趣的人可以參考 Removing White Chars from ASP.NET Output using Response.Filter property 這篇文章。

在我前幾天寫的 ASP.NET MVC 開發心得分享 (3):與 WebForm 共舞 文章中,就有提到如何透過 jQuery 將 ViewState 相關的隱藏欄位刪除,不過若是透過 Response.Filter 屬性的應用將會更完美,而我今天就是用這個例子來練習應用 Response.Filter 屬性的。

我今天寫了一個 HttpModule 專案用來對所有 ASP.NET MVC 頁面進行過濾動作,效果感覺還不錯。另外,今天也心血來潮跑去 CodePlex 建立一個新專案,並將今天寫的專案與原始碼都上傳上去了,有興趣的人可以到 ASP.NET MVC Friendly HttpModule 下載。

這個專案包含兩個 Stream 類別與一個 HttpModule,分別是:

  1. StripViewStateStream
    運用 Regular Expression 技巧將所有 ViewState 相關標籤全部消除
  2. StripNamingContainerStream
    將所有包含有 NamingContainer 的多餘名稱全部移除
  3. MvcFriendlyModule
    在 BeginRequest 事件裡要定義 Response.Filter 屬性需套用的 Stream 類別

MvcFriendlyModule 中主要程式如下,可以一次套用兩個自訂的 Stream 類別:

void context_BeginRequest(object sender, EventArgs e)
{
    HttpApplication app = (HttpApplication)sender;

    if (app.Context.Response.ContentType == "text/html")
    {
        app.Context.Response.Filter =
            new StripNamingContainerStream(
                new StripViewStateStream(
                    app.Context.Response.Filter
                )
            );
    }
}

若你下載下載之後只要將 dll 加入到你現有的 ASP.NET MVC 專案,定設定網站的 web.config 加入 MvcFriendlyModule 模組即安裝完畢。

<httpModules>
    ....
    <add name="MvcFriendlyModule"
         type="MvcFriendlyModule.MvcFriendlyModule, MvcFriendlyModule"/>
    ....
</httpModules>

除了直接套用 HttpModule 到全網站之外,你也可以僅套用在單一網頁中,也可以只單套用其中一個 Stream 就好。例如在 ViewPage 中可以寫在 Page_Init 事件中:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
         Inherits="System.Web.Mvc.ViewPage" %>
<%@ Import Namespace="MvcFriendlyModule" %>
<script runat="server">
   1:  
   2:     protected void Page_Init(object sender, EventArgs e)
   3:     {
   4:         Response.Filter = new StripNamingContainerStream(Response.Filter);
   5:     }
</script>

其實除了 Response.Filter 屬性外,還有一個 Request.Filter 屬性,用法完全一樣,可以讓你過濾所有經由 HTTP Post 進來的 Stream 資料 ( HTTP Request Body )。

相關連結