ASP .NET Web Developer s Guide - Mesbah Ahmed, Chris Garrett
.pdf270Chapter 6 • Optimizing Caching Methods
■VaryByParam
■VaryByHeader
■VaryByCustom
When ASP.NET generates the content of your page, the output can vary based on values that have been passed to the page. By using the VaryByParam attribute, you can control the caching of these pages based on a GET query string or POST parameters. By specifying the GET query string parameters or POST parameters using this attribute, each request received for that parameter using a different value will be cached. For example, if you specified the “name” GET query string parameter, each request received with a different name value will be cached separately.The syntax for setting a 60-second cache with the “name” parameter is as follows:
<% @ OutputCache Duration="60" VaryByParam="name" %>
If you use the “name” parameter with the VaryByParam attribute as shown in the previous code, and the requests shown in Figure 6.1 are received, ASP.NET will cache three pages, each for a duration of 60 seconds.
Figure 6.1 Sample Page Requests
http://LocalHost/testing/mypage.aspx?name=bob
http://LocalHost/testing/mypage.aspx?name=bob&cube=C4
http://LocalHost/testing/mypage.aspx?name=charlie
http://LocalHost/testing/mypage.aspx?name=chris&cube=A4
http://LocalHost/testing/mypage.aspx?name=chris&ext=5555
If the requests arrived in the order specified in Figure 6.1, the first, third, and fourth pages will be cached. For the duration of their time in the cache, any request with the name parameter containing these three names will be satisfied by redisplaying the cached data.
You can specify multiple parameters to the VaryByParam attribute by separating them with a semicolon. For example, using the code:
<% @ OutputCache Duration="60" VaryByParam="name;cube" %>
would result in caching four pages instead of three, if the requests specified in Figure 6.1 were received. In this case, the first, second, third, and fourth pages would be cached. Figure 6.2 shows the source of a small application demonstrating
www.syngress.com
Optimizing Caching Methods • Chapter 6 |
271 |
the use of the VaryByParam attribute.This code is located on the CD that accompanies this book as output_cache.aspx. Figures 6.3, 6.4, and 6.5 display the generated page after clicking on each button. Each page is stored in cache for 60 seconds.
Figure 6.2 Output Cache Example Code (output_cache.aspx0
<% @ OutputCache Duration=60 VaryByParam="button" %>
<HTML>
<SCRIPT language="VB" runat="server">
Sub Page_Load(Src As Object, E As EventArgs)
TimeMsg.Text = DateTime.Now.ToString("G")
PageName.Text = request.querystring("button")
End Sub </SCRIPT>
<BODY>
<H3>Output Cache Example</H3>
<FORM action=output_cache.aspx method=get> <P><H4>Click a button</H4>
<INPUT type="submit" name="button" value="One"> <INPUT type="submit" name="button" value="Two"> <INPUT type="submit" name="button" value="Three"> </FORM>
<P>Page generated at: <asp:label id="TimeMsg" runat="server"/> <P>Page Name: <asp:label id="PageName" runat="server"/>
</BODY>
</HTML>
www.syngress.com
272 Chapter 6 • Optimizing Caching Methods
Figure 6.3 Output Cache Example Page 1
Figure 6.4 Output Cache Example Page 2
www.syngress.com
Optimizing Caching Methods • Chapter 6 |
273 |
Figure 6.5 Output Cache Example Page 3
The second available attribute, VaryByHeader, enables you to control output caching based on the HTTP header that is passed to the page during a request. This opens up the option of caching multiple versions of pages based on any header variable. A partial list of acceptable HTTP header values available in this context is shown in Table 6.2.
Table 6.2 HTTP Headers
|
HTTP Headers |
Description |
|
|
|
|
ACCEPT |
Acceptable media types |
|
ACCEPT-CHARSET |
Acceptable character sets |
|
ACCEPT-ENCODING |
Acceptable content coding values |
|
ACCEPT-LANGUAGE |
Acceptable languages (based off ISO639-2 |
|
|
standards) |
|
ACCEPT-RANGES |
Acceptable range requests |
|
AGE |
The amount of time since the response was |
|
|
generated |
|
ALLOW |
Methods supported by the server |
|
AUTHORIZATIOn |
Authorization credentials used for a request |
|
|
|
|
|
Continued |
www.syngress.com
274 Chapter 6 • Optimizing Caching Methods
Table 6.2 Continued
HTTP Headers |
Description |
|
|
CACHE-CONTROL |
Cache control directives |
CONNECTION |
Options that are specified for a particular connec- |
|
tion and must not be communicated by proxies |
|
over further connections |
COOKIE |
Cookies associated with the request |
DATE |
Date and time of request origination |
FROM |
E-mail address of the requesting user (if provided) |
HOST |
Address and port of the requested resource |
MAX-FORWARDS |
Number of proxies or gateways allowed between |
|
the requestor and the destination server |
MIME-VERSION |
The version of MIME used to construct the message |
MSTHEMECOMPATABLE |
Allow or disallow theme support (Only available in |
|
IE6+) |
REFERER |
URI of the user’s last request |
REQUEST-METHOD |
The verb used for the request |
SET-COOKIE |
Value of the cookie set for the request |
TRANSFER-ENCODING |
Message body encoding type |
USER-AGENT |
Information about the user agent (browser) making |
|
the request |
As an example, we could cache multiple versions of a page that differs based on the accepted language of the requestor.This would be accomplished by specifying the Accept-Language parameter to the VaryByHeader attribute as shown in the following code:
<% @ OutputCache Duration="60" VaryByParam="none"
VaryByHeader="Accept-Language" %>
If three requests are then received with the Accept-Language header values specified in Figure 6.6, two will be cached. Because the third request matches the first, the third request will be fulfilled by the data that was previously cached by the first request.
www.syngress.com
Optimizing Caching Methods • Chapter 6 |
275 |
Figure 6.6 Sample Header Values
en-us
en-uk
en-us
The final available attribute is VaryByCustom.This attribute enables you to control caching of the page based on browser version or other custom strings that you define. If you were to want to cache multiple versions of a page based on the browser type of the requestor, you would use the “browser” parameter with the VaryByCustom attribute.
<% @ OutputCache Duration="60" VaryByParam="none"
VaryByCustom="browser" %>
This code has the effect of caching a different version of the page for every request coming from different browser types and versions based on the page’s Request.Browser.Type property. If a request is made from an Opera browser and an Internet Explorer browser, two versions of the page are made available in the output cache for subsequent requests.
Using the HttpCachePolicy Class
Another method of setting the output cache for a page is to use the HttpCachePolicy class.This property enables you to control the caching policy at a much more granular level. In the first sample for the @ OutputCache directive, we set the cache for a duration of 60 seconds with no other parameters. To perform the same function using the HttpCachePolicy class, you could use this code:
Response.Cache.SetExpires(DateTime.Now.AddSeconds(60))
Response.Cache.SetCacheability(HttpCacheability.Public)
This sets the cache expiration to be 60 seconds from the current system time and gives the page public cache visibility.There are several other properties that can be set for the HttpCacheability method.These properties are listed and explained in Table 6.3.
www.syngress.com
276 Chapter 6 • Optimizing Caching Methods
Table 6.3 HttpCacheability Method Values
Value |
Description |
|
|
NoCache |
This can be specified with or without an optional fieldname. |
|
When no field name is specified, the value applies to the entire |
|
request, and any shared cache such as a proxy server must |
|
requery the Web server instead of sending the cached page. |
|
When a field is specified, only the specified field will require a |
|
requery, and the rest of the page can be sent from the shared |
|
cache. |
Private |
This is the default value. When this is specified, the page will be |
|
cached only on the client end, and will not be cached by a shared |
|
cache such as a proxy server. |
Public |
By setting the public value, the page can be cached by a shared |
|
cache as well as by the client cache. |
Server |
This value specifies that the page has only to be cached on the |
|
Web server and not the client or a shared cache. |
If you would like the cache duration to be extended each time the page is requested, the SetSlidingExpiration method can be set to true.This property defaults to false, which sets the page to expire when the time set in the SetExpires method lapses.
Response.Cache.SetSlidingExpiration(true)
It is generally best to use the @ OutputCache directive at the beginning of your page and only use the HttpCachePolicy class when you need a lower level of control over the caching header. Either of these methods can provide the same functionality, and the only reasons to use one over the other is the level of control that you need and the ease of use.
Advantages of Using Output Caching
The primary advantage of output caching is speed.When a page is cached using output caching, the entire page is stored in memory for the duration specified; therefore, the response to a request for this page is almost instantaneous. Implementing output caching within your application can increase the performance by several hundred percent depending on your content. Consider the access time difference between running a query against a remote database compared to pulling a page directly from memory.
In addition, the usage of output caching cuts down on the number of requests sent to your database server.When a page is dynamically generated for
www.syngress.com
Optimizing Caching Methods • Chapter 6 |
277 |
the first time, the data necessary is queried and then presented to the user. If the page is subsequently stored in cache, the database does not need to be queried in order to present the requested information.This can increase performance of your database server by eliminating many unnecessary queries.
Fragment Caching
In order to work with pages that have some dynamic content that needs to be updated regularly, as well as content that remains relatively static, Microsoft has provided the concept of fragment caching.This enables you to break your page into separate sections (fragments) that can be cached individually with their own caching options.
Using fragment caching is very similar to output caching. In fact, you call it in the same way as output caching by using either the @ OutputCache directive or the HttpCachePolicy class. Fragment caching is implemented by separating user controls out of your main page, and assigning caching parameters to each user control.This gives you a greater level of control over which portions of your page are cached.
An example of a good use for fragment caching is when you have a table within a page that has content generated from a database. In order to cut down on the number of queries being sent to the database, you want to cache the data in the table for a specified time period. However, the page that the table is displayed in has a timestamp that must be updated.The way we would accomplish this is to place the code used for generating the table into a user control and call the control from within the main page.This code is illustrated in Figures 6.7 and 6.8.
Figure 6.7 Fragment Cache Example Code Part 1 (fragment_cache.aspx)
<!— First we set up the user control —>
<%@ Register TagPrefix="Tag1" TagName="TestControl" Src="fragment_cache.ascx" %>
<HTML>
<SCRIPT language="VB" runat="server">
Sub Page_Load(Src As Object, E As EventArgs)
' We'll just load the current date/time into a string
Continued
www.syngress.com
278 Chapter 6 • Optimizing Caching Methods
Figure 6.7 Continued
TimeMsg.Text = DateTime.Now.ToString("G")
End Sub
</SCRIPT>
<BODY>
<H3>Fragment Cache Example</H3>
<!— We'll run the user control first —>
<Tag1:TestControl runat="server"/>
<!— Then show the time that this page was loaded —>
<P>Main page generated at: <asp:label id="TimeMsg" runat="server"
/>
</BODY>
</HTML>
Figure 6.8 Fragment Cache Example Code Part 2 (fragment_cache.ascx)
<!— We'll set the cache up for a two minute duration —>
<%@ OutputCache Duration="120" VaryByParam="none" %>
<SCRIPT language="VB" runat="server">
Sub Page_Load(Src As Object, E As EventArgs)
' We'll just load the current date/time into a string
TimeMsg.Text = DateTime.Now.ToString("G")
End Sub
</SCRIPT>
<P>
Continued
www.syngress.com
Optimizing Caching Methods • Chapter 6 |
279 |
Figure 6.8 Continued
<!— In real use, we'd use data from a database for this. We'll just make our
own table for the example. —>
<TABLE border=1 bordercolor=brown> <TR bgcolor=lightyellow>
<TH>First Name</TH>
<TH>Last Name</TH> <TH>Number</TH>
</TR>
<TR>
<TD>Bob</TD>
<TD>Marly</TD> <TD>555-1234</TD>
</TR>
<TR>
<TD>Lee</TD>
<TD>Young</TD> <TD>555-1235</TD>
</TR>
</TABLE>
<!— Show the time that this control was loaded —>
<P>Table last generated on: <asp:label id="TimeMsg" runat="server" />
These code fragments are on the included CD as fragment_cache.aspx and fragment_cache.ascx. In the second code fragment, I am generating the table data within the code; however, fragment caching in this style is best used when you are pulling data from database tables.When this code is run, you will see two timers as shown in Figure 6.9.The first will list the time that the table was built. This is the time that the user control was called, and based on the @ OutputCache directive, this user control will be cached for 120 seconds.The second timer will show the time that the main page was generated. As no caching parameters were
www.syngress.com