Caching Parts of the Page


Output caching the contents of a page is very powerful but not always possible. For example, in many cases, content (such as advertisements or user-specific information) must be dynamic. Page output caching can’t be used in these scenarios, so ASP.NET supports partial page caching technology, which allows only part of the page output to be cached.

Partial page caching allows for regions of a page to be cached while other regions are executed dynamically. The ASP.NET control gallery (found at http://www.asp.net), shown in Figure 6-8, is an example. Areas within Figure 6-8 that are grayed-out represent content that is output cached; areas that are not grayed-out represent areas that are not output cached.

click to expand
Figure 6-8: The ASP.NET control gallery, with only some content output cached

As you can clearly see, a lot of content is cached, but a large percentage of the content is also not cached. Content that can be shared for multiple users, such as top 10 lists, featured controls, or the list of the available controls, are not cached. However, content that is personalized, such as the displayed tabs or the discussion forum, are rendered dynamically on each request.

This ability to partially cache content on the page is incredibly useful because we can still derive the benefits of not doing unnecessary work on each request. Partial page caching employs user controls to divide regions of the page. In Figure 6-8, the page is divided into several user controls, each identified within a black-bordered rectangle.

User controls, which are server controls, are best thought of as pages that can be reused in other pages. For example, you can think of the Top 10 Controls as a stand-alone page capable of displaying just this data. This page can then be composed with other pages to present a single unified view. User controls use the special extension .ascx, and nearly all user control can have their extension renamed to .aspx and run as normal pages. The beauty of user controls is that they are programmed in a way that is similar to programming pages, but they can be reused as server controls by other pages. Code Listings 6-1 and 6-2 represent the source code to the 10 Ten Controls user control from the http://www.asp.net Control Gallery.

Code Listing 6-1: MostPopularControls.ascx

start example
 <%@ Control language="C#" EnableViewState="false" %> 
<%@ OutputCache Duration="60" VaryByParam="none" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="server">
public void Page_Load(Object sender, EventArgs e) {
SqlConnection connection;
SqlCommand command;

// Initialize connection and command
connection = new SqlConnection([connection string]);
command = new SqlCommand("CG_Top10Controls", connection);
command.CommandType = CommandType.StoredProcedure;

connection.Open();
ControlList.DataSource = command.ExecuteReader();
ControlList.DataBind();
connection.Close();

}
</script>

<span >
Below are the top 10 most popular controls today.
</span>
<p>
<asp:datalist runat="server" >
<itemtemplate>
<li>
<a href="/ControlGallery/ ControlDetail.aspx?control=<%# DataBinder.Eval(Container.DataItem, "Id") %>&tabindex=2"><%# DataBinder. Eval(Container.DataItem, "Name") %></a>
</itemtemplate>
</asp:datalist>
end example

Code Listing 6-2: Page Using a User Control

start example
 <%@ Register TagPrefix="ControlGallery"
TagName="MostPopular"
src="/books/2/540/1/html/2/MostPopularControls.ascx" %>
<Font size=3>Top 10 Controls</Font>
<ControlGallery:MostPopular runat=server />
end example

To enable the partial page output caching feature, we simply add output cache directives to the user control instead of to the page. For example, to output cache the Top 10 Control list, we simply add the following directive to the MostPopularControls.ascx user control:

<%@ OutputCache Duration="60" VaryByParam="none" %> 

When the page is requested, ASP.NET builds what is known as a control tree. The page is the top node, and controls are added in order beneath the appropriate parent controls, as shown in Figure 6-9. In the figure, the literal content <Font size=3>Top 10 Controls</Font> is stored in a literal control, and the user control is stored as a UserControl.


Figure 6-9: Control tree

When a user control is found that supports caching, ASP.NET does a bit of trickery whereby it inserts a special control, shown in the following code and in Figure 6-10.

System.Web.UI.PartialCachingControl 

click to expand
Figure 6-10: Control tree with PartialCachingControl

In Figure 6-10, the UserControl that is marked as output cached is replaced with a PartialCachingControl. When the control tree is created, the PartialCachingControl retrieves it’s output from the cache. If the output is not found, the original user control is rendered and the contents are added to the cache.

This control is inserted into the control tree where the output cached control should be. The PartialCachingControl represents a cached view of the user control. If the PartialCachingControl finds contents in the cache for the user control, it uses that as its output; otherwise, it calls Render on the user control, stores its contents in the cache for subsequent use, and then renders itself.

Although this scenario sounds complex, the good news is that programming partial page output caching feels very similar to programming page output caching. The bad news is that partial page output caching supports only page directives and has no programmatic API.

Partial page output caching does support two concepts not found in the output cache directives for pages:

  • Varying by control state

  • Shared user control cache entries

Varying By Control State

Partial page caching supports the concept of varying by parameters using the standard vary-by syntax, which allows the output cached user control to vary its content by HTTP GET (querystring) or HTTP POST parameters:

<%@ OutputCache Duration="60" VaryByParam="tabindex" %> 

However, user controls can also participate within a <form runat="server" />, whereby the user control might contain an input element, such as a drop-down list, which can be posted back to the server. For example, when using the Control Gallery at http://www.asp.net, you can view multiple control summaries simultaneously, such as Form Controls, as shown in Figure 6-11.

click to expand
Figure 6-11: Viewing multiple control summaries simultaneously

The display in Figure 6-11 is an output-cached user control and by default is shown filtered by Date Last Updated. However, when the user filters by a different option, such as Most Downloads, the list re-sorts itself according to this new criteria. This newly filtered output is also served from the cache.

However, no VaryByParam option is used, because the name of the parameter that is sent via HTTP POST cannot be easily deduced. (The name of the control cannot be easily deduced because it is a subcontrol of <form/>, which is a naming container and prepends information to contained control IDs so that it can uniquely identity controls within that naming container.) Instead, the VaryByControl option is used, naming the control to vary by. In this case the control is a DropDownList control with an ID of FilterControls:

<% OutputCache Duration="600" 
VaryByParam="none"
VaryByControl="FilterControls" %>

<asp:DropDownList runat="server" >

</asp:DropDownList>

When the control is rendered in the browser, its name value is as follows:

<select name="_ctl2:ControlList:_ctl0:FilterControls" > 

When the control is posted back to the server, it won’t be named FilterControls. If we attempt to specify VaryByParam="FilterControls", we wouldn’t get the desired behavior—since that’s not the control’s name!

Rather, the VaryByControl is simply aware of how the name of the contained controls is changed to guarantee uniqueness within the page. So instead of having to decode the name, we can rely upon the VaryByControl attribute to give us the correct behavior.

Tip

Don’t use VaryByParam="*", which would also resolve to an unknown HTTP POST parameter name. Instead use the VaryByControl option.

Shared User Control Cache Entries

In ASP.NET 1.0, the user control caching model created a separate entry in the cache for each use of a user control. Thus, if the same cached user control is used to generate a navigation menu and it is used on 50 pages, 50 entries would appear in the cache for this user control.

In ASP.NET 1.1, we added a new Shared attribute that can be specified in the directive. This attribute instructs ASP.NET to share any instances of the user control rather than create new entries in the cache for each control. In ASP.NET 1.1, then, you could specify the following:

<%@ OutputCache Duration="60" VaryByParam="none" Shared="true" %> 

This directive instructs ASP.NET to share the cached version of the control across all pages.




Microsoft ASP. NET Coding Strategies with the Microsoft ASP. NET Team
Microsoft ASP.NET Coding Strategies with the Microsoft ASP.NET Team (Pro-Developer)
ISBN: 073561900X
EAN: 2147483647
Year: 2005
Pages: 144

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net