ASP.NET Page緩存提高異步更新時的性能
ASP.NET Page是個非常強大的模型,緩存是它的重要特性。本文結合UpdatePanel的簡單實例講解ASP.NET的緩存技術。如果一個頁面已經使用了緩存,我還沒有想到一個操作簡單,但又能保持其緩存特性的 解決方案 。另外,我甚至想合理利用這種緩存機制來提高異步更新
ASP.NET Page是個非常強大的模型,緩存是它的重要特性。本文結合UpdatePanel的簡單實例講解ASP.NET的緩存技術。如果一個頁面已經使用了緩存,我還沒有想到一個操作簡單,但又能保持其緩存特性的
解決方案。另外,我甚至想合理利用這種緩存機制來提高異步更新時的
性能(也就是嘗試著讓頁面緩存異步更新的內容)。
我查閱了ASP.NET Page緩存的資料,作了一些嘗試,但是依舊無法得出一個比較好的解決方案??赡艿拇_是scriptManager替代頁面輸出方法造成的問題吧,既然無法在那時處理緩存,又如何能夠避免頁面緩存的問題,甚至利用緩存來提高性能呢?
ASP.NET Page是個非常強大的模型,緩存是它的重要特性。一個成熟的ASP.NET應用程序幾乎都會使用緩存,它能夠顯著得提高性能,減少服務器端生成頁面或者控件內容的消耗。不過現在出現了UpdatePanel這個“神奇”的控件,如果使用緩存不當,就會讓我們的應用程序出現錯誤。
UpdatePanel的功能大家一定都非常熟悉了。無論是官方還是社區里熱心推廣ASP.NET AJAX的朋友,都會對于UpdatePanel的使用進行大量說明與展示。
但是在這些簡單的的示例似乎都遺漏了一個非常重要的問題,這個問題會直接導致UpdatePanel無法正確使用。
這個問題就是ASP.NET Page的緩存。
重現問題
我們還是來編寫一個使用UpdatePanel的簡單示例,如下:
CachedPage.aspx
<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ OutputCache Duration="100" VaryByParam="None" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Cached Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:scriptManager ID="scriptManager1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<%= DateTime.Now.ToString() %>
<asp:Button ID="Button1" runat="server" Text="Async PostBack" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:Button ID="Button2" runat="server" Text="PostBack" />
</form>
</body>
</html>
我們打開頁面,依次做一下操作,并察看頁面上顯示的時間。
多次刷新頁面,時間不會改變。
多次點擊Async PostBack按鈕,頁面部分刷新,時間每次都會改變。
多次點擊PostBack按鈕,頁面完全刷新,時間只會更新一次,然后時間保持不變。
點擊Async PostBack按鈕,發生錯誤。
直到等待時間超過100秒(Cache過期),點擊Async PostBack才工作正常,直到用戶再次點擊過PostBack按鈕。
分析問題
使用Fiddler等工具察看出現錯誤時的Response Body,會發現頁面返回了整張頁面的內容,而不是UpdatePanel熟悉的特殊的字符串。要說明這個問題,需要再了解一下UpdatePanel的工作方式。
點擊Async PostBack按鈕之后,客戶端采集頁面上所有的信息,使用XMLHttpRequest發起一個請求,并且會在請求的Header信息中設置一個x-microsoftajax的值為Delta=true。
服務器端的Page頁面接受到請求之后,并不會得知這是由XMLHttpRequest發出的請求,因此和常規一樣進行頁面中所有的工作,例如觸發控件事件等等。
頁面上的scriptManager控件在OnInit時,一旦發現Request的Header里有正確的x-microsoftajax信息,將會意識到目前在進行異步的PostBack。
如果scriptManager得知現在正在異步PostBack,則在OnPreRender時調用Pate.SetRenderDelegate方法,提供自定義的方法用于輸出頁面。
在自定義的輸出方法中,scriptManager采集所有的信息(例如哪些UpdatePanel進行了更新,需要輸出的腳本等等),并且輸出客戶端能夠識別的內容。
客戶端收到信息后,對其進行分析,并且更新頁面。
在正常情況下,這個流程應該順利的跑完,但是如果頁面內容在服務器端被緩存了呢?將會出現下面的情況:
點擊Async PostBack按鈕,客戶端采集頁面上所有的信息,使用XMLHttpRequest發起一個請求。
Page在接受到請求之后,發現頁面中存在緩存信息、并且緩存沒有過期,于是直接輸出緩存中的頁面內容。
客戶端收到了完整的頁面內容,無法識別,拋出異常。