[翻譯]asp.net 2.0中通過壓縮ViewState改善效能

來源:互聯網
上載者:User
原文地址:http://www.dotnetbips.com/articles/22d33d11-1a75-42c8-bbf6-ca1a345d3fcf.aspx
[原文源碼下載]

[翻譯]asp.net 2.0中通過壓縮ViewState改善效能

原文發布日期:2007.03.08
作者:Bipin Joshi
翻譯:webabcd

介紹
開發人員經常擔心他們web網站的效能。每一個開發人員都想他們的web網站的效能是最佳化的。影響你web網站效能的有很多因素,ViewState就是其中之一。本文我將給大家提供一個通過壓縮ViewState來改善效能的方法。

什麼是ViewState
雖然本文並不是專門來研究ViewState的,但我們還是簡單的討論一下吧。你如果看過web form產生的HTML代碼的話,就會發現在一個名為__VIEWSTATE的隱藏欄位。聰明的ASP.NET會持久化這些控制項的值到這個隱藏欄位中,這對於往返伺服器的過程中儲存控制項的值是非常有用的。但是,此時ViewState會帶來效能問題。因為ViewState要在服務端與用戶端之間傳輸,所以會增加網路頻寬的流量。

要減少ViewState的話,可以關閉ViewState,就是設定控制項的EnableViewState屬性,如果設定該屬性為false則控制項的ViewState將被關閉。但是,如果沒有ViewState的話,控制項狀態持久化的工作就需要你自己來做了,這將是令人非常頭痛的。還有另一種減少ViewState的方法就是本文將要介紹的方法,即在ViewState傳輸之前先壓縮它,這樣ViewState的資料將會大幅度減少。

在ASP.NET 1.x中如果我們要使用壓縮功能的話需要自己寫一些代碼。而現在.NET 2.0提供了System.IO.Compression命名空間,將會使壓縮功能的實現變得非常簡單。System.IO.Compression命名空間的GZipStream類可以處理流的壓縮和解壓,注意,GZipStream只能以流的方式工作。GZipStream類不知專門壓縮ViewState而設計的,所以我們為了實現ViewState的壓縮和解壓要自己寫一些代碼。

開發ViewStateHelper
我們首先用Visual Studio建立一個web網站,然後再App_Code檔案夾中增加一個名為ViewStateHelper的類。類檔案頂部要引入的命名空間如下using System.IO;
using System.IO.Compression;

System.IO命名空間為我們提供了流的類,如MemoryStream。The System.IO.Compression命名空間為我們提供GZipStream類,它允許你呈現gzip格式的資料(RFC 1952)。

壓縮資料
現在增加一個名為Compress()的方法如下public static byte[] Compress(byte[] data)
{
    MemoryStream ms = new MemoryStream();
    GZipStream stream = new GZipStream(ms, CompressionMode.Compress);
    stream.Write(data, 0, data.Length);
    stream.Close();
    return ms.ToArray();
}

這個Compress()靜態方法接收一個位元組數群組類型的變數並壓縮它,返回的是一個壓縮後的位元組數組。它首先執行個體話一個MemoryStream類,它用來呈現記憶體中的流。然後通過MemoryStream和壓縮模式兩個參數建立一個GZipStream對象。你可以用任何流類型來替換MemoryStream。被壓縮的資料將寫進這個流。GZipStream類的Write()方法會接收一個位元組數群組類型的變數,然後壓縮它並寫進流中(在我們的例子中是MEmoryStream)。寫完之後GZipStream被關閉。最後,MemoryStream的ToArray()方法將轉換流資料到位元組數組中。

解壓資料
為瞭解壓資料,我們要增加另一個名為Decompress()的方法,其關鍵代碼如下public static byte[] Decompress(byte[] data)
{
    MemoryStream ms = new MemoryStream();
    ms.Write(data, 0, data.Length);
    ms.Position = 0;
    GZipStream stream = new GZipStream(ms, CompressionMode.Decompress);
    MemoryStream temp = new MemoryStream();
    byte[] buffer = new byte[1024];
    while (true)
    {
        int read = stream.Read(buffer, 0, buffer.Length);
        if (read <= 0)
        {
            break;
        }
        else
        {
            temp.Write(buffer, 0, buffer.Length);
        }
    }
    stream.Close();
    return temp.ToArray();
}

這個Decompress()靜態方法接收一個已壓縮的位元組數組,返回一個解壓後的位元組數組。首先,它建立了一個MemoryStream對象,並將一個已壓縮的位元組數組寫進去。然後這個流將作為參數提供給GZipStream的建構函式,注意此時的壓縮模式為Decompress。解壓後的資料也需要在某個地方儲存,所以接下來建立的另一個MemoryStream對象就是作此用途。接著我們用一個while迴圈從GZipStream讀取出解壓後的資料,每一塊都是1024位元組。然後這個資料就被寫進MemoryStream了。最後,GZipStream被關閉,解壓後的內容作為一個位元組數組被返回。

建立一個web form
現在開啟一個web form,拖拽一個SqlDataSource控制項到上面,配置它以使其可以從Northwind資料庫中讀取Customers表的記錄。

拖拽一個GridView控制項並設定它的DataSourceID屬性為你剛才配置好的SqlDataSource控制項的ID。確保運行這個web form是我們想要的結果,樣本如下

定製ViewState的序列化和還原序列化
你不用關心ViewState的序列化和還原序列化,因為這些都是自動的。但是因為咱們需要壓縮ViewState,所以需要定製它的序列化和還原序列化。Page基類有兩個虛擬方法,SavePageStateToPersistenceMedium()和LoadPageStateFromPersistenceMedium()。它們分別允許你定製ViewState的序列化和還原序列化。

我們首先在web form的後置代碼中重寫SavePageStateToPersistenceMedium()方法。在這個方法中,你將壓縮ViewState並儲存它到隱藏欄位中。代碼如下protected override void SavePageStateToPersistenceMedium(object state)
{
    LosFormatter formatter = new LosFormatter();
    StringWriter writer = new StringWriter();
    formatter.Serialize(writer, state);
    string viewState = writer.ToString();
    byte[] data = Convert.FromBase64String(viewState);
    byte[] compressedData = ViewStateHelper.Compress(data);
    string str = Convert.ToBase64String(compressedData);
    ClientScript.RegisterHiddenField("__MYVIEWSTATE", str);
}

SavePageStateToPersistenceMedium()方法接收一個ViewState對象。在該方法中建立一個LosFormatter對象,LosFormatter類允許你序列化和還原序列化ViewState中的資料。LosFormatter類的Serialize()方法接收兩個參數,分別是一個流和一個對象,結果是把這個對象序列化到這個流中。在我們的例子裡,ViewState被序列化到了StringWriter裡。StringWriter的ToString()方法返回一個字串用於呈現ViewState資料。這個字串是Base64格式的(在ASP.NET中就是這麼儲存到ViewState中的),我們需要把它轉換成我們想要的格式。Convert類的FromBase64String()方法就可以做這個工作。FromBase64String()方法返回一個位元組數組資料,然後使用我們的ViewStateHelper類的Compress()方法壓縮它。然後使用Convert類的ToBase64String()方法把被壓縮的資料轉換成Base64格式。最後,我們用ClientScript的RegisterHiddenField()方法把這個已壓縮的Base64格式的資料註冊到一個名為__MYVIEWSTATE的隱藏欄位中。

這就是我們壓縮ViewState的方法。另外還有一個同等重要的工作就是解壓,我們通過重寫LoadPageStateFromPersistenceMedium()方法來實現這樣的功能,其代碼如下protected override object LoadPageStateFromPersistenceMedium()
{
    string viewstate = Request.Form["__MYVIEWSTATE"];
    byte[] data = Convert.FromBase64String(viewstate);
    byte[] uncompressedData = 
    ViewStateHelper.Decompress(data);
    string str = Convert.ToBase64String(uncompressedData);
    LosFormatter formatter = new LosFormatter();
    return formatter.Deserialize(str);
}

這個方法首先讀出__MYVIEWSTATE隱藏欄位的值,該值為Base64格式的被壓縮ViewState。為瞭解壓它,你的第一步工作仍然是把它轉換為一個位元組數組,我們通過Convert類的FromBase64String()方法來做。接下來我們用ViewStateHelper類的Decompress()方法解壓資料。然後用Convert類的ToBase64String()方法再一次把解壓後的資料轉換為Base64格式的字串。最後,LosFormatter對象還原序列化解壓後的ViewState

以上就是壓縮和解壓ViewState的全部內容。經過我對本例的實際測試發現未經壓縮的ViewState大小為13,568位元組,壓縮後的ViewState大小為5,932位元組。這對於改善效能是非常有用的,你說呢?

總結
從本文中你學到了如何通過壓縮ViewState來改善你web網站的效能。GZipStream類提供了現成的把你的資料壓縮成gzip格式的方法。被壓縮的資料需要通過重寫Page基類的SavePageStateToPersistenceMedium()方法儲存。相似的,讀取ViewState後我們需要通過重寫LoadPageStateFromPersistenceMedium()來解壓資料。

作者:Bipin Joshi
Email:http://www.dotnetbips.com/contact.aspx
簡介:Bipin Joshi是DotNetBips.com的管理員。他是http://www.binaryintellect.com/的發起人,這個公司提供.NET framwork的培訓和諮詢服務。他在印度孟買為開發人員提供培訓。他也是微軟的MVP(ASP.Net)和ASPInsiders的會員。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.