Using the Page Output Cache

only for RuBoard

Page output caching is the method of caching the output of an entire page. After the page is rendered and cached, all subsequent requests for the page are served from the memory resident version until it is removed ” taken out of the cache.

Page output caching can be done in two ways. The first uses the @OutputCache directive (seen in Listing 16.1), and the second uses the HttpCachePolicy class. Essentially, they accomplish the same thing, but by using the @OutputCache directive, you are accessing the HttpCachePolicy class through a higher-level, user -friendly wrapper.

In this section, I will discuss how to use both methods to enable page output caching. I will review their properties that enable you to vary the way in which the items are cached, based on different criteria, such as query string parameters or browser types.

Using the @OutputCache Directive to Enable Caching

Listing 16.1 illustrated how to use the @OutputChache directive to quickly enable page output caching. However, the directive's implementation is a catchall caching mechanism. The @OutputCache directive has five attributes available to control output caching in web forms. These attributes control how long an item can be cached, where an item can be cached (Server, Client Browsers), and ways to create multiple representations of one document. Before going into each attribute available, let's look at the @OutputCache directives general syntax:

 01: <%@ OutputCache Duration="value" Location="value" VaryByCustom="value" graphics/ccc.gif VaryByHeader="value" VaryByParam="value" %> 

We will be going over each of these attributes in the following sections.

The Duration Attribute

The Duration attribute appeared in Listing 16.1. The Duration attribute specifies the duration in seconds that an item should remain in a cache. Unlike other caching mechanisms, such as the cache APIs, there is no way to designate an exact time to take items out of the cache using the Duration attribute. (I will discuss absolute expiration times later in the chapter.)

Duration is one of the @OutuputCache directives required attributes and you would receive an exception if you didn't include it. Listing 16.2 contains an example using the @OutputCache 's Duration attribute.

Listing 16.2 Using the Duration Attribute
 [VisualBasic.NET & C#.NET] 01: <%@ OutputCache Duration="60" VaryByParam="none" %> 02: <html> 03: <body> 04: This page was cached at: 05: <b> 06:  <%=DateTime.Now.ToString("G")%> 07: </b> 08: </body> 09: </html> 

The Duration attribute is set on line 1 within the @OutputCache directive. When this page is rendered, it will be cached for 60 seconds. After the 60 seconds has elapsed, the next request for the page will be placed in the cache.

The Location Attribute

The Location attribute enables you to control where an item can be cached. For instance, using the Location attribute, you can specify that you only want the cached documents to be located on the server that processed the original request. Or, you could stipulate that only clients , such as Internet browsers, can cache the page.

The following values can be used for the Location attribute. They can be found in the OutputCacheLocation enumeration within the System.Web.UI namespace:

  • Any The output cache can be located on the server that processed the request, on the client's browser, or on a downstream server. Essentially, caching will take place anywhere it can. Any is the default value for the Location attribute.

  • Client The output cache can be only on the client's browser.

  • Downstream The output cache can be only on a server downstream from the server that processed the request.

  • None The output cache is disabled for the requested page.

  • Server The output cache can be only on the server that processed the request.

Listing 16.3 contains an example of using the Location attribute. I recommend playing with all five possible values of this attribute so you can see how changing the value affects caching.

Listing 16.3 Using the Location Attribute
 [VisualBasic.NET & C#.NET] 01: <%@ OutputCache Duration="60" VaryByParam="none" Location="Server" %> 02: <html> 03: <body> 04: This page was cached at: 05: <b> 06:  <%=DateTime.Now.ToString("G")%> 07: </b> 08: </body> 09: </html> 

In Listing 16.3 I used Server as the value for the Location attribute, which means that the cached document will always be supplied to the client from the server. I recommend playing with all the different attributes so you can see the differences. One example I suggest trying would be to set the value to Client , if the value is Client , the browser will maintain control of the cache until the cache duration time has elapsed (if caching is enabled on the client). Unlike when server caching is enabled, if the Refresh button is clicked; a request will be made to the server and the server dynamically generates a new version of the document for the client. When the Refresh button is clicked with server caching enabled, documents are still served by the server to the client on each request, but clients are served the cached version rather than a version that is being dynamically generated.

The VaryByParam Attribute

You have seen how to control where a document is cached using the Location attribute, and how to control the amount of time that it should remain in the cache using the Duration attribute, but you haven't seen how to vary the way that a document is cached. By "vary," I mean being able to have multiple representations of the same document cached. The VaryByParam is one of the @OutputCache attributes that enables you to do this by using query string parameter values and the parameters of a Form POST .

As you'll recall in Listing 16.3, the VaryByParam attribute has a value of none . When the value is set to none , only one representation of the page is cached. However, page content often varies based on parameters, so using none as a value would not be an option. For example, a page might have Mode passed as a query string parameter (Ex: news.aspx?mode=# ) ” mode=1 renders current news and mode=2 renders old news. Using the VaryByParam attribute enables you to cache two representations of news.aspx by using the values of Mode , 1 and 2 . After each version of news.aspx document is cached, subsequent requests would be served from either of the two cached versions. For this example, you would write your @OutputCache directive as follows :

 <%@ OutputCache Duration="69" VaryByParam="  Mode  " %> 

You are not limited to just one value; you can specify multiple values to vary the cache on by separating the values with semicolons:

 <%@ OutputCache Duration="69" VaryByParam="  Mode;   Newstype  " %> 

You also might choose to vary the cache by every possible combination. You can use an * as the value to do this:

 <%@ OutputCache Duration="69" VaryByParam="*" %> 

Listing 16.4 and 16.5 illustrate how to cache multiple representations of the same document based on query string parameters.

Listing 16.4 Using the VaryByParam Attribute to Vary How a Document Is Cached Based on Query String Parameter Values
 [VisualBasic.NET] 01: <%@ OutputCache Duration="160" Location="Server" VaryByParam="num;num2" %> 02: 03: <%@ Import Namespace="System.Data" %> 04: <%@ Import Namespace="System.Data.SqlClient" %> 05: 06: <script language="vb" runat="server"> 07: 08:  public sub Page_Load(sender as Object, e as EventArgs) 09: 10:  try 11: 12:   dim nvc as NameValueCollection = Request.QueryString 13:   dim sqlCmd as new StringBuilder() 14:   dim sQueryStringValues as new StringBuilder() 15:   dim i,ii as Integer 16:   dim KeyArray(),ValueArray() as String 17: 18: '*** Build string to show query string keys in Label control 19:   KeyArray = nvc.AllKeys 20: 21:   sQueryStringValues.Append("<b>Query string parameter(s):<br>") 22: 23:   for i = 0 to KeyArray.Length - 1 24:    sQueryStringValues.Append(KeyArray(i)) 25:    ValueArray = nvc.GetValues(i) 26:    for ii = 0 to ValueArray.Length - 1 27:     sQueryStringValues.Append("=" & ValueArray(ii) & "<br>") 28:    next ii 29:   next i 30: 31:   sQueryStringValues.Append("</b>") 32: 33:   QueryStringValues.Text = sQueryStringValues.ToString() 34: '*** End 35: 36: '*** Get data from database based on num value 37:  if nvc.GetValues("num")(0) <> nothing then 38: 39:   dim ds as new DataSet() 40:   dim sCon as new SqlConnection("server=localhost;" & _ 41:     "uid=sa;pwd=;database=northwind") 42: 43: 44:   sqlCmd.Append("SELECT TOP ") 45:   sqlCmd.Append(nvc.GetValues("num")(0)) 46:   sqlCmd.Append(" * FROM Products") 47: 48:   dim sda as new SqlDataAdapter(sqlCmd.ToString(),sCon) 49:   sda.Fill(ds,"Products") 50: 51:   dg1.DataSource = ds.Tables(0).DefaultView 52:   dg1.DataBind() 53: 54:   end if 55: '*** End 56: catch nullEx as NullReferenceException 57:  ErrorMessage.Text = nullEx.Message 58: end try 59:  end sub 60: 61: </script> [C#.NET] 06: <script language="c#" runat="server"> 07: 08:  void Page_Load(Object sender , EventArgs e){ 09: 10:  try { 11: 12:   NameValueCollection nvc = Request.QueryString; 13:   StringBuilder sqlCmd = new StringBuilder(); 14:   StringBuilder sQueryStringValues = new StringBuilder(); 15:   int i,ii; 16:   string[] KeyArray,ValueArray; 17: 18: //'*** Build string to show query string keys in Label control 19:   KeyArray = nvc.AllKeys; 20: 21:   sQueryStringValues.Append("<b>Query string parameter(s):<br>"); 22: 23:   for (i = 0; i < KeyArray.Length; i++){ 24:    sQueryStringValues.Append(KeyArray[i]); 25:    ValueArray = nvc.GetValues(i); 26:    for (ii = 0; ii < ValueArray.Length; ii++) { 27:     sQueryStringValues.Append("=" + ValueArray[ii] + "<br>"); 28:     } 29:    } 30: 31:   sQueryStringValues.Append("</b>"); 32: 33:   QueryStringValues.Text = sQueryStringValues.ToString(); 34: //'*** End 35: 36: //'*** Get data from database based on num value 37:  if (nvc.GetValues("num")[0] != null){ 38: 39:   DataSet ds = new DataSet(); 40:   SqlConnection sCon = new SqlConnection("server=localhost;" + 41:     "uid=sa;pwd=;database=northwind"); 42: 43: 44:   sqlCmd.Append("SELECT TOP "); 45:   sqlCmd.Append(nvc.GetValues("num")[0]); 46:   sqlCmd.Append(" * FROM Products"); 47: 48:   SqlDataAdapter sda = new SqlDataAdapter(sqlCmd.ToString(),sCon); 49:   sda.Fill(ds,"Products"); 50: 51:   dg1.DataSource = ds.Tables[0].DefaultView; 52:   dg1.DataBind(); 53: 54:   } 55: //'*** End 56: }  catch (NullReferenceException nullEx) { 57:  ErrorMessage.Text = nullEx.Message; 58:  } 59: } 60: 61: </script> [VisualBasic.NET & C#.NET] 62: <html> 63: <body> 64: 65: This page was cached at:&nbsp;<b><%=DateTime.Now.ToString("G")%></b> 66: <br> 67: <asp:Label id="QueryStringValues" runat="server" /> 68: <p> 69: <asp:datagrid runat="server" id="dg1" font-size="10" /> 70: <p> 71: <asp:Label id="ErrorMessage" runat="server" /> 72: </body> 73: </html> 

The @OutputCache directive is located on line 1 of Listing 16.4. Notice that the VaryByParam attribute contains two values separated by a semicolon, num and num2 . This means that this document will be cached based on the values of both these names (parameters). When this page renders, you will see three things: the date and time this document was cached, a list of the query string parameters passed in the URL, and a DataGrid control with ( n ) number of rows. The num query string parameter determines the value of ( n ).

The second half of this example, found in Listing 16.5, contains the code for the start page. This page contains only a handful of links that navigate to Listing 16.4 with different query string values.

Listing 16.5 The Start Page for Listing 16.4
 [VisualBasic.NET & C#.NET] 01: <html> 02: <body> 03: <b><u>Pick how many rows to show</u>:</b> 04:  <p> 05: <b>Show Top 5</b> 06: <br> 07:  <a href="Listing16.4.aspx?num=5"> 08:   [Listing16.4.aspx?num=5] 09:  </a> 10: <br> 11:  <a href="Listing16.4.aspx?num=5&num2=1"> 12:   [Listing16.4.aspx?num=5&num2=1] 13:  </a> 14: <p> 15: <b>Show Top 15</b> 16:  <br> 17:  <a href="Listing16.4.aspx?num=15"> 18:   [Listing16.4.aspx?num=15] 19:  </a> 20:  <br> 21:  <a href="Listing16.4.aspx?num=15&num2=1"> 22:   [Listing16.4.aspx?num=15&num2=1] 23:  </a> 24:  <p> 25: <b>Show Top 10</b> 26:  <br> 27:  <a href="Listing16.4.aspx?num=10"> 28:   [Listing16.4.aspx?num=10] 29:  </a> 30:  <br> 31:  <a href="Listing16.4.aspx?num=10&num2=1"> 32:   [Listing16.4.aspx?num=10&num2=1] 33:  </a> 34:  <p> 35: <b>Show Top 20</b> 36:  <br> 37:  <a href="Listing16.4.aspx?num=20"> 38:   [Listing16.4.aspx?num=20] 39:  </a> 40:  <br> 41:  <a href="Listing16.4.aspx?num=20&num2=1"> 42:   [Listing16.4.aspx?num=20&num2=1] 43:  </a> 44: </body> 45: </html> 

Listing 16.5 contains eight different links to the same page (Listing 16.4). Each link has the same set of parameters; however, the values of each are different. Using these links, I will demonstrate how to cache multiple representations of the same document. After you have the start page up, you should receive a page similar to Figure 16.1.

Figure 16.1. The start page for Listing 16.4, which contains eight different links with the same parameters, but with different values.
graphics/16fig01.gif

If you walk through the following steps, you will get a better handle on how the VaryByParam parameter affects caching:

  1. Start at the Show Top 5 links. Click and navigate to the Listing 16.4 page. (Make a note of the time that the document was cached on each.)

  2. Proceed down the line until you have navigated to every link and made a note of the cache time.

  3. Start back at the Show Top 5 section and navigate all the hyperlinks again. While doing this, check the cache times with the cache times of your first pass through.

During your first pass through, you will find that every one of the links produces a new cache time. This is because the values of one or more of the parameters are always different, so a new cache is created. On your second pass through, you'll find that all the cache times did not change from the first pass through. This is because, on the second pass through, the documents are being served from the cached documents that have the same parameter values. You can also open two different browsers and request the same page from both. You will produce the same results as the previous walk through ”both browsers will have the same cache time.

Try adding a third parameter on the results page, but don't change the original parameters. You'll find that the document is still served from a cached document matching the first two parameters because the third parameter is not set as a value in the VaryByParam attribute. If you were to add the newly added parameter to the VaryByParam attribute, an additional cache item would be created. Figures 16.2 and 16.3 show the results page after the first and second Show Top 5 links are selected, respectively. The cache times are different.

Figure 16.2. The results page after Show Top 5 with one parameter is selected.
graphics/16fig02.gif
Figure 16.3. Results page after Show Top 5 with two parameters is selected.
graphics/16fig03.gif

In Figure 16.2, the cache time is 9:13:01 p.m .

In Figure 16.3 the cache time is 9:13:12 p.m . By setting the VaryByParam attribute to both num and num2 , I have created and cached two representations of the document. The next time that either of these two documents is requested before their cache duration expires , the document will be served to the client from the server cache.

You may, at this point, have concerns over all these memory resident items eating up your memory. Every item put into the cache has both a priority (its priority in the cache over other objects) and decay rate (the rate an items priority falls when its not frequently accessed ” Normal to Low ). As memory fills up items are taken out of the cache based on these values. The output cache by default has a very low priority rate and a very high decay rate. Therefore, if there are pages in the cache that are not frequently accessed they will be taken out of the cache to free up memory, while others that are accessed frequently are kept in the cache longer.

The VaryByCustom Attribute

You might want to vary the way that a document is cached to something other than the inherent attributes. The ASP.NET development team realized this and created a VaryByCustom attribute. VaryByCustom enables you to specify a string as a value, and caching will take place based on the value of this string. The VaryByCustom attribute does have one "Out of the box" value that you can use ” Browser . When set to Browser , a new cache item is created for each type of browser that requests the document based on the browser name and major version.

You can use a custom value for the VaryByCustom attribute by overriding the HttpApplication.GetVaryByCustomString method in the Global.asax file. Listing 16.6 demonstrates implementing your own value for the VaryByCustom attribute. This example creates a new cache item based on a user . Listing 16.7 contains the code for the global.asax file. Listing 16.8 is code to put into your Web.config file to implement authentication. And, finally, Listing 16.9 contains a mock login page. For this example to work properly you must have all four examples in one Web application and a request must first be made to Listing 16.6.

Listing 16.6 Web Form Implementing the VaryByCustom Attribute.
 [VisualBasic.NET] 01: <%@ OutputCache Duration="160" Location="Server" VaryByCustom="UserProfile" graphics/ccc.gif VaryByParam="none" %> 02: 03: <%@ Import Namespace="System.Data" %> 04: <%@ Import Namespace="System.Data.SqlClient" %> 05: 06: <script language="vb" runat="server"> 07: 08:  public sub Page_Load(sender as Object, e as EventArgs) 09: 10:   try 11: 12:    UserName.Text = Context.User.Identity.Name 13: 14:    dim sqlCmd as new StringBuilder() 15:    dim ds as new DataSet() 16:    dim sCon as new SqlConnection("server=localhost;" & _ 17:     "uid=sa;pwd=;database=northwind") 18: 19:    sqlCmd.Append("SELECT TOP 5") 20:    sqlCmd.Append(" * FROM Products") 21: 22:    dim sda as new SqlDataAdapter(sqlCmd.ToString(),sCon) 23:    sda.Fill(ds,"Products") 24: 25:    dg1.DataSource = ds.Tables(0).DefaultView 26:    dg1.DataBind() 27: 28:  catch Sex as SqlException 29: 30:   ErrorMessage.Text = Sex.Message 31: 32:  end try 33: 34: end sub 35: 36: public sub SignOutNow(sender as Object, e as EventArgs) 37: 38:  FormsAuthentication.SignOut() 39: 40: end sub 41: 42: </script> [C#.NET] 01: <%@ OutputCache Duration="160" Location="Server" VaryByCustom="UserProfile" graphics/ccc.gif VaryByParam="none" %> 02: 03: <%@ Import Namespace="System.Data" %> 04: <%@ Import Namespace="System.Data.SqlClient" %> 05: 06: <script language="c#" runat="server"> 07: 08:  void Page_Load(Object sender, EventArgs e) { 09: 10:   try { 11: 12:    UserName.Text = Context.User.Identity.Name; 13: 14:    StringBuilder sqlCmd = new StringBuilder(); 15:    DataSet ds = new DataSet(); 16:    SqlConnection sCon = new SqlConnection("server=localhost;" + 17:     "uid=sa;pwd=;database=northwind"); 18: 19:    sqlCmd.Append("SELECT TOP 5"); 20:    sqlCmd.Append(" * FROM Products"); 21: 22:    SqlDataAdapter sda = new SqlDataAdapter(sqlCmd.ToString(),sCon); 23:    sda.Fill(ds,"Products"); 24: 25:    dg1.DataSource = ds.Tables[0].DefaultView; 26:    dg1.DataBind(); 27: 28:  }  catch (SqlException Sex) { 29: 30:   ErrorMessage.Text = Sex.Message; 31: 32:  } 33: 34: } 35: 36: public void SignOutNow(Object sender, EventArgs e) { 37: 38:  FormsAuthentication.SignOut(); 39: 40: } 41: 42: </script> [VisualBasic.NET & C#.NET] 43: <html> 44: <body> 45: <form runat="server" > 46: This page was cached at:&nbsp;<b><%=DateTime.Now.ToString("G")%></b> 47: <br> 48: Hello: <asp:Label id="UserName" runat="server" /> 49: <p> 50: <asp:Button id="SignOut" OnClick="SignOutNow" 51:  Text="Sign Out" runat="Server" /> 52: <p> 53: <asp:datagrid runat="server" id="dg1" font-size="10" /> 54: <p> 55: <asp:Label id="ErrorMessage" runat="server" /> 56: </form> 57: </body> 58: </html> 

On line 1 of Listing 16.6, the @OutputCache directive's VaryByCustom attribute is set to UserProfile . During the Page_Load event, I set the UserName Label controls Text property to the authenticated user (line 12). On line 46, I printed out the time that this document was cached. Listing 16.7 contains the code needed to implement the UserProfile as a valid value for the VaryByCustom attribute within the global.asax file. Notice the "Sign Out" button in the page; you can use this to sign out and become unauthenticated or to test how caching differs between users.

Listing 16.7 Overriding the GetVaryByCustomString in the global.asax File
 [VisualBasic.NET] 01: <script lanaguage="vb" runat="server"> 02: 03: public overrides function GetVaryByCustomString (Context As HttpContext, CustomArgs graphics/ccc.gif As String) As String 04: 05:  select CustomArgs 06:  case "UserProfile" 07:    return "UserName=" & Context.User.Identity.Name 08:  case else 09:    return "Browser=" & Context.Request.Browser.Browser 10:  end select 11: 12: end function 13: 14: </script>  [C#.NET] 01: <script language="c#" runat="server"> 02: 03: public override string GetVaryByCustomString (HttpContext Context, string arg){ 04: 05:  switch (arg){ 06:   case "UserProfile": 07:    return "UserName=" + Context.User.Identity.Name; 08:    break; 09:   default: 10:    return "Browser=" + Context.Request.Browser.Browser; 11:    break; 12:  } 13: 14: } 15: 16: </script> 

Start off by overriding the GetVaryByCustomString method in Listing 16.7. This method has two parameters, and the first is the HttpContext . The second is a string that will be the value of the VaryByCustom attribute. The VaryByCustom attribute within Listing 16.6 is UserProfile , so this is what will be passed in as a parameter when the page is requested. On line 5, I used a select statement (C# switch ) for the CustomArgs parameter. I did this because each page can implement its own VaryByCustom attribute, so that you potentially can have multiple custom attributes being passed into this method. The GetVaryByCustomString method returns a string that determines how the cache is varied. If the method returns a string on which the cache has already been varied, then it is considered a hit, and the document isn't cached. If the method returns a string on which the cache has not already been varied, then it is considered a miss , and the document will be cached. Listing 16.8 contains the code necessary to implement authentication to test out the VaryByCustom attribute. In this example, a new cache item for this document will be created for each authenticated user.

Listing 16.8 has the code for the web.config file, used to implement forms authentication. Listing 16.9 contains the code for login.aspx , which must be saved in the application root directory. Otherwise, you must change the LoginUrl attribute to reflect any directory changes.

Listing 16.8 Code for web.config File
 01: <configuration> 02:  <system.web> 03:   <authentication mode="Forms"> 04:    <forms name=".DOTNETJUNKIE" loginUrl="C16/listing16.6.aspx" protection="all" graphics/ccc.gif timeout="60" /> 05:     </authentication> 06:     <authorization> 07:     <deny users="?" /> 08:    </authorization> 09:  </system.web> 10: </configuration> 

Note

You might need to change the loginUrl attribute in Listing 16.8 to reflect your Web application, like this:

 loginUrl="Directory/WebForm.aspx" 

Listing 16.9 Web Form for the Login Page
 01: <script language="vb" runat="server"> 02: 03:  public sub Login_Click(sender as Object, e as EventArgs) 04: 05:   FormsAuthentication.RedirectFromLoginPage(username.Text, true) 06: 07:  end sub 08: 09: </script> [C#] 01: <script language="c#" runat="server"> 02: 03:  void Login_Click(Object sender, EventArgs e) 04:  { 05: 06:   FormsAuthentication.RedirectFromLoginPage(username.Text, true); 07: 08:  } 09: </script> [VisualBasic.NET & C#.NET] 10: <html> 11: <body> 12: <form runat="server"> 13: <h3>Login Form</h3> 14: User Name: <asp:TextBox id="username" runat="server" /> 15: <br> 16: <asp:Button runat="server" onclick="Login_Click" id="Login" text="Login" /> 17: </form> 18: </body> 19: </html> 

Because the code in Listings 16.8 and 16.9 doesn't demonstrate caching and is used only to implement authentication, I haven't analyzed it.

After all code is implemented and a page request is made to Listing 16.6, your browser will be redirected to Listing16.6.aspx . After you enter a login name and click the login button, you will be redirected back to the page from Listing 16.6. You will see the cache time, your login name, and a DataGrid rendered to the page. To really see the variation in the cache, you will either have to request the page from a computer other than localhost, or log out and log back in using the Log Out button. Also, if you have two different types of browsers installed on your computer (IE and Netscape) you can open the page in each and log in under a different name since they won't share sessions. Figure 16.4 and Figure 16.5 contain screen shots of two requests from two different users.

Figure 16.4. Listing 16.6 after logging in as Donny Mack. Note the difference in the cache time from Figure 16.5.
graphics/16fig04.gif
Figure 16.5. Listing 16.6 logging in as Doug Seven on a different computer.
graphics/16fig05.gif

As you can see, the cache time is different for both users. This trend will continue for each and every new user who logs on to your site. As users leave and new users log on, cache items automatically will be taken out of the cache based on time and importance.

Caution

The VaryByCustom attribute is not supported by user controls.


The VaryByHeader _attribute

Another way you can vary how a page is cached is by HTTP Header information that is passed to the server by the client during a page request. The attribute that allows this type of caching is VaryByHeader . An example would be User-Agent , which is a description of the browser that made the original request:

 "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)" 

The following lists useful Request HTTP Headers you can use as a value for the VaryByHeader attribute:

  • Accept

  • Accept-Charset

  • Accept-Encoding

  • Accept-Language

  • Authorization

  • Content-Encoding

  • Expect

  • From

  • Host

  • If-Match

  • If-Modified-Since

  • If-None-Match

  • If-Range

  • If-Unmodified-Since

  • Max-Forwards

  • Proxy-Authorization

  • Range

  • Referer

  • TE

  • User-Agent

Using the VaryByHeader attribute is just a matter of adding one or more Header names, separated by semicolons (;) as a value for VaryByHeader :

 <%@ OutputCache Duration="60" VaryByParam="none" VaryByHeader="User-Agent; Referer%> 

In the preceding code, the requested document will be cached based on both the User-Agent Header (browser information) and the Referer (the location that the user navigated from to request this document).

Caution

The VaryByHeader attribute is not supported by user controls.


only for RuBoard


Programming Data-Driven Web Applications with ASP. NET
Programming Data-Driven Web Applications with ASP.NET
ISBN: 0672321068
EAN: 2147483647
Year: 2000
Pages: 170

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