說到網站性能優化,沒有什麼比“緩存”更重要了。即便是某些朋友口中念念不忘的“靜態頁”,說 到底也只是緩存了整張頁面內容而已。但是,顯然這樣大粒度的緩存策略,在如今“牽一發而動全身”的 Web 2.0站點中幾乎是無法使用的。試想,在Twitter中的某個名人被數十萬人訂閱,那麼他發一條消息, 難道此時網站要去修改數十萬用戶的靜態頁面?因此,我們需要粒度更小的緩存。而比“整頁緩存”粒度 小一號的緩存,便是所謂“視圖片斷緩存”了。
視圖片斷緩存非常重要,因為它緩存的也是頁面內容,這表示它比更低級別的緩存更有效率,也比靜 態頁等整頁內容緩存的適用面要大得多。在ASP.NET WebForm模型中提供了控件級別的緩存,我們可以為 控件標記輸出緩存策略,這樣控件便不會每次都完整執行一遍。當然這個策略還不夠靈活,因為它緩存的 最小單元是“控件”,而不是頁面中任意的部分。因此我在一年多前提出了一個CachePanel,由它包裝的 頁面內容都可以被緩存,無論其內部是控件還是普通輸出的內容。在實際生產過程中,CachePanel起到了 非常重要的作用,許多場景下只要在頁面中包裹一個<ext:CachePanel runat="server" />,性能 立即就有了質的飛躍。
只可惜,在如今ASP.NET MVC的時代無法直接使用CachePanel這樣的服務器端控件。因為CachePanel需 要服務器端代碼的配合,而ASP.NET MVC中的頁面只是“視圖模板”,除了呈現之外就不應該有其他職責 。因此,我們必須提出一種脫離於後端代碼的“標記”方式,將視圖中的內容片斷進行隨意地緩存。在 Rails或Django中都有類似的特性,但ASP.NET MVC甚至在2.0的Road Map中還沒有包含這一功能,於是我 們只能自己動手豐衣足食。不過有了ASP.NET WebForm作為強大的視圖引擎,加這樣的功能簡直是舉手之 勞:
public static class CacheExtensions
{
public static string Cache
(
this HtmlHelper htmlHelper,
string cacheKey,
CacheDependency cacheDependencies,
DateTime absoluteExpiration,
TimeSpan slidingExpiration,
Func<object> func)
{
var
cache = htmlHelper.ViewContext.HttpContext.Cache;
var content = cache.Get
(cacheKey) as string;
if (content == null)
{
content = func().ToString();
cache.Insert(cacheKey, content,
cacheDependencies, absoluteExpiration, slidingExpiration);
}
return content;
}
}