共用方式為


將動態內容新增至快取的頁面 (C#)

Microsoft 提供

了解如何在相同的頁面中混合動態和快取的內容。 快取後替換可讓您在快取輸出的頁面內顯示動態內容,例如橫幅廣告或新聞項目。

您可以藉由利用輸出快取,大幅改善 ASP.NET MVC 應用程式的效能。 可以產生一次頁面並在記憶體中快取,以供多個使用者使用,而不是每次請求頁面時都重新產生頁面。

不過,有一個問題。 如果您需要在頁面中顯示動態內容,該怎麼做? 例如,假設您想要在頁面中顯示橫幅廣告。 您不想要快取橫幅廣告,讓每個使用者都看到完全相同的廣告。 這樣您就賺不到錢了!

還好有一個簡單的解決方案。 您可以善用稱為快取後替換的 ASP.NET 架構功能。 快取後替換,可讓您在記憶體中快取的頁面中替換動態內容。

一般而言,當您使用 [OutputCache] 屬性輸出快取頁面時,頁面會在伺服器和用戶端上快取 (網頁瀏覽器)。 當您使用快取後替換時,只能在伺服器上快取頁面。

使用快取後替換

使用快取後替換需要兩個步驟。 首先,您必須定義方法,這個方法會傳回字串,其代表您想要在快取頁面中顯示的動態內容。 接下來,您會呼叫 HttpResponse.WriteSubstitution() 方法,將動態內容插入頁面。

假設您想要在快取頁面中隨機顯示不同的新聞項目。 清單 1 中的 類別會公開名為 RenderNews() 的單一方法,該方法會從三個新聞項目清單中隨機傳回一個新聞項目。

清單 1 – Models\News.cs

using System;
using System.Collections.Generic;
using System.Web;

namespace MvcApplication1.Models
{
    public class News
    {
        public static string RenderNews(HttpContext context)
        {
            var news = new List<string> 
                { 
                    "Gas prices go up!", 
                    "Life discovered on Mars!", 
                    "Moon disappears!" 
                };
            
            var rnd = new Random();
            return news[rnd.Next(news.Count)];
        }
    }
}

若要利用快取後替換功能,您可以呼叫 HttpResponse.WriteSubstitution() 方法。 WriteSubstitution() 方法會設定程式碼,以動態內容取代快取頁面的區域。 WriteSubstitution() 方法可用來在清單 2 的檢視中顯示隨機新聞項目。

清單 2 – Views\Home\Index.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<!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>Index</title>
</head>
<body>
    <div>

    <% Response.WriteSubstitution(News.RenderNews); %>
        
    <hr />
    
    The content of this page is output cached.
    <%= DateTime.Now %>

    </div>
</body>
</html>

RenderNews 方法會傳遞至 WriteSubstitution() 方法。 請注意,不會呼叫 RenderNews 方法 (沒有括號)。 相反的,方法的參考會傳遞至 WriteSubstitution()。

已快取索引檢視。 檢視是由清單 3 中的控制器傳回。 請注意,Index() 動作是以 [OutputCache] 屬性裝飾,導致索引檢視快取 60 秒。

清單 3 – Controllers\HomeController.cs

using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        [OutputCache(Duration=60, VaryByParam="none")]
        public ActionResult Index()
        {
            return View();
        }
    }
}

即使快取索引檢視,當您要求索引頁面時,也會顯示不同的隨機新聞項目。 當您要求 [索引] 頁面時,頁面顯示的時間不會變更 60 秒 (請參閱圖 1)。 時間不會變更的事實證明頁面已快取。 不過,WriteSubstitution() 方法插入的內容 (隨機新聞項目) 會隨著每個要求而變更。

圖 1 – 在快取頁面中插入動態新聞項目

clip_image002

在 Helper 方法中使用快取後替換

利用快取後替換的較簡單方式是在自訂 Helper 方法中封裝 WriteSubstitution() 方法的呼叫。 這個方法是由清單 4 中的 Helper 方法所說明。

清單 4 – AdHelper.cs

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication1.Helpers
{
    public static class AdHelper
    {
        public static void RenderBanner(this HtmlHelper helper)
        {
            var context = helper.ViewContext.HttpContext;
            context.Response.WriteSubstitution(RenderBannerInternal);
        }
        
        private static string RenderBannerInternal(HttpContext context)
        {
            var ads = new List<string> 
                { 
                    "/ads/banner1.gif", 
                    "/ads/banner2.gif", 
                    "/ads/banner3.gif" 
                };

            var rnd = new Random();
            var ad = ads[rnd.Next(ads.Count)];
            return String.Format("<img src='{0}' />", ad);
        }
    }
}

清單 4 包含公開兩種方法的靜態類別:RenderBanner() 和 RenderBannerInternal()。 RenderBanner() 方法代表實際的 Helper 方法。 這個方法會擴展標準 ASP.NET MVC HtmlHelper 類別,如此您就可以在檢視中呼叫 Html.RenderBanner(),就像任何其他 Helper 方法一樣。

RenderBanner() 方法會呼叫 HttpResponse.WriteSubstitution() 方法,將 RenderBannerInternal() 方法傳遞至 WriteSubstitution() 方法。

RenderBannerInternal() 方法是私用方法。 此方法不會公開為 Helper 方法。 RenderBannerInternal() 方法會從三個橫幅廣告影像清單中隨機傳回一個橫幅廣告影像。

清單 5 中修改過的索引檢視說明如何使用 RenderBanner() Helper 方法。 請注意,檢視頂端包含一個附加的 <%@ Import %> 指示詞,用於匯入 MvcApplication1.Helpers 命名空間。 如果您忽略匯入此命名空間,則 RenderBanner() 方法不會顯示為 Html 屬性上的方法。

清單 5 – Views\Home\Index.aspx (with RenderBanner() method)

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<%@ Import Namespace="MvcApplication1.Helpers" %>
<!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>Index</title>
</head>
<body>
    <div>

    <% Response.WriteSubstitution(News.RenderNews); %>
    
    <hr />
    
    <% Html.RenderBanner(); %>
    
    <hr />
    
    The content of this page is output cached.
    <%= DateTime.Now %>

    </div>
</body>
</html>

當您在清單 5 中要求檢視轉譯的頁面時,每個要求都會顯示不同的橫幅廣告 (參見圖 2)。 快取頁面,但橫幅廣告會由 RenderBanner() helper 方法動態注入。

圖 2 – 顯示隨機橫幅廣告的索引檢視

clip_image004

摘要

本教學課程說明您可以如何在快取頁面中動態更新內容。 您已了解如何使用 HttpResponse.WriteSubstitution() 方法來讓動態內容注入快取的頁面。 您也了解如何在 HTML helper 方法中封裝 WriteSubstitution() 方法的呼叫。

盡可能利用快取 , 可能會對 Web 應用程式的效能產生巨大影響。 如本教學課程所述,即使您需要在頁面中顯示動態內容,仍可以利用快取。