除了輸出緩衝整頁外,ASP.NET 還為您提供了輸出快取頁面內容地區的簡單方法,此方法被恰當地稱作片段快取。使用使用者控制項勾劃頁面的地區,並使用上節介紹的
@ OutputCache 指令將它們標記為供緩衝使用。此指令指定使用者控制項的輸出內容在伺服器上緩衝的期間(以秒為單位),以及改變此期間所依據的可選條件。
例如,下列指令指示 ASP.NET 輸出緩衝使用者控制項 120 秒,並使用“CategoryID”和“SelectedID”查詢字串或表單發布參數改變緩衝。
<%@ OutputCache Duration="120" VaryByParam="CategoryID;SelectedID"%>
VaryByParam 屬性功能十分強大,它允許使用者控制項作者指示 ASP.NET 在伺服器上緩衝/儲存輸出快取區域的多個執行個體。例如,前一個使用者控制項的宿首頁的下列 URL 緩衝使用者控制項內容的單獨執行個體。
http://localhost/mypage.aspx?categoryid=foo&selectedid=0
http://localhost/mypage.aspx?categoryid=foo&selectedid=1
使用者控制項內的邏輯因此能夠根據提供的參數動態產生不同的內容(單獨緩衝)。
除了支援 VaryByParam 屬性外,片段快取還支援 VaryByControl 屬性。VaryByParam 屬性基於使用 POST 或 GET 發送的成對的名稱和數值改變緩衝結果,而 VaryByControl 屬性則通過使用者控制項中的控制項改變緩衝片段。例如:
<%@ OutputCache Duration="120" VaryByParam="none" VaryByControl="Category" %>
注意:與輸出快取頁面相似,即使不使用 VaryByParam,也要求顯式使用它。
如果使用者控制項包含名為“Category”的下拉選擇框控制項,使用者控制項的輸出將基於在該控制項中選擇的值改變。
正如可以在頁中遞迴嵌套使用者控制項(即在另一伺服器控制項中聲明的使用者控制項)一樣,也可以遞迴嵌套輸出緩衝使用者控制項。這提供了一個功能強大的撰寫模型,此模型使緩衝的地區能夠由進一步子緩衝的地區組成。
下面的範例程式碼說明如何使用聲明性使用者控制項快取頁面的兩個菜單部分。
<%@ Register TagPrefix="Acme" TagName="Menu" Src="Menu.ascx" %> <html> <body> <table> <tr> <td> <Acme:Menu Category="LeftMenu" runat=server/> </td> <td> <h1>Hi, the time is now: <%=DateTime.Now%> </h1> </td> <td> <Acme:Menu Category="RightMenu" runat=server/> </td> <tr> </table> </body> </html> <%@ Register TagPrefix="Acme" TagName="Menu" Src="Menu.ascx" %> <html> <body> <table> <tr> <td> <Acme:Menu Category="LeftMenu" runat=server/> </td> <td> <h1>Hi, the time is now: <%=Now%> </h1> </td> <td> <Acme:Menu Category="RightMenu" runat=server/> </td> <tr> </table> </body> </html> <%@ Register TagPrefix="Acme" TagName="Menu" Src="Menu.ascx" %> <html> <body> <table> <tr> <td> <Acme:Menu Category="LeftMenu" runat=server/> </td> <td> <h1>Hi, the time is now: <%=DateTime.Now%> </h1> </td> <td> <Acme:Menu Category="RightMenu" runat=server/> </td> <tr> </table> </body> </html> |
| C# |
VB |
JScript |
|
下面的範例程式碼顯示具有緩衝支援的"Acme:Menu"使用者控制項的實現。
<%@ OutputCache Duration="120" VaryByParam="none" %> <script language="C#" runat=server> public String Category; void Page_Load(Object sender, EventArgs e) { AdoConnection conn = new AdoConnection("MyDSN"); MyMenu.DataSource = conn.Execute("select * from menu where category=" + Category ); MyMenu.DataBind(); } </script> <asp:datagrid id="MyMenu" runat=server/> <%@ OutputCache Duration="120" VaryByParam="none" %> <script language="VB" runat=server> Public Category As String; Sub Page_Load(sender As Object, e As EventArgs) Dim conn As AdoConnection = New AdoConnection("MyDSN") MyMenu.DataSource = conn.Execute("select * from menu where category=" & Category) MyMenu.DataBind() End Sub </script> <asp:datagrid id="MyMenu" runat=server/> <%@ OutputCache Duration="120" VaryByParam="none" %> <script language="JScript" runat=server> public var Category:String; function Page_Load(sender:Object, e:EventArgs) : void { var conn:AdoConnection = new AdoConnection("MyDSN"); MyMenu.DataSource = conn.Execute("select * from menu where category=" + Category ); MyMenu.DataBind(); } </script> <asp:datagrid id="MyMenu" runat=server/> |
| C# |
VB |
JScript |
|
注意:此樣本將每個使用者控制項的響應輸出緩衝 120 秒。在緩衝未命中(因為已超過 120 秒,或者因為伺服器上的記憶體已變得不足)時重建每個菜單使用者控制項所需的全部邏輯完全封裝在使用者控制項中。
下面的樣本顯示了簡單的片段快取。此樣本緩衝從 SQL Server 資料庫檢索資料的控制項的輸出,同時保持父頁的動態屬性。可以看到頁是動態,因為時間隨著每次重新整理而更新,而控制項只是每隔 60 秒更新一次。
注意事項
注意:試圖以編程方式從輸出緩衝控制項的包含頁對該輸出緩衝控制項進行操作將導致錯誤。例如,試圖在使用者控制項標記上使用聲明性資料繫結運算式將產生分析錯誤,如下列代碼所示。
<!-- The following tags generate parser errors. --> <Acme:Menu Category='<%# Container.DataItem("Category")' runat="server"/>
其中的原因很簡單。在使用者控制項的內容被輸出緩衝的情況中,僅在第一次請求時建立控制項的執行個體;因此,控制項一旦緩衝將不再可用。相反,應該將建立使用者控制項內容所需的全部邏輯直接封裝在控制項本身中;這通常在使用者控制項的 Page_Load 事件或 Page_PreRender 事件中完成。
可以聲明和使用其他聲明性屬性參數來自訂控制項。例如,可以如下自訂前面的使用者控制項:
<Acme:Menu Category="LeftMenu" runat=server/> <Acme:Menu Category="RightMenu" runat=server/>
這些聲明導致在因緩衝未命中而建立控制項時,產生適當的代碼並由頁編譯器來執行這些代碼。這樣,使用者控制項開發人員就可以像在非緩衝使用者控制項情況中那樣訪問這些設定。