Output Caching Overview
Output caching can be set programmatically using the HttpCachePolicy class, or declaratively by using the OutputCache page or control directive. The primary attributes for output caching are as follows:
|
Attribute |
Description |
|
Duration |
The time, in seconds, that a page will be cached at the client. Sliding expiration can be set programmatically for server-side cache using the SetSlidingExpiration() method of the HttpCachePolicy class. |
|
Location |
The location where the page or user control will be cached. Values can be Any (the default value, caching can be wherever applicable, i.e. the client browser, proxy server, or Web server), Client, Downstream (client or proxy server), None (no caching), and Server. |
|
VaryByCustom |
A string that indicates either the browser or custom string that is used to vary cache. Note: This parameter can only be used in server-side cache. |
|
VaryByHeader |
A semicolon delimited list of HTTP headers for which to vary the output cache. Note: This attribute only applies to server-side cache and must be used with the Duration attribute. |
|
VaryByParam |
A semicolon delimited list of parameters for which to vary output cache. |
Note that the Output directive requires two parameters: VaryByParam and Duration. If VaryByParam does not apply then set its value to None. Output caching at the client is retrieved only by the page’s URL and not the page’s version, thus VaryByCustom, VaryByHeader, and VaryByParam apply only to server-side cache.
Examples of using these attributes would be as follows:
|
Caching at proxy servers and the client:
Page Directive Approach
<%@ OutputCache Duration="3600" Location="Downstream" VaryByParam="None" %>
Programmatic Approach
Response.Cache.SetExpires(DateTime.Now.AddSeconds(3600));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetNoServerCaching(); |
|
Caching variations of a page at the server based on browser type:
Page Directive Approach
<%@ OutputCache Duration="3600" VaryByHeader="User-Agent" VaryByParam="None" %>
Programmatic Approach
Response.Cache.SetExpires(DateTime.Now.AddSeconds(3600));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.VaryByHeaders["User-Agent"] = true; |
|
Caching variations of a page based upon a DropDownList control’s selection:
Page Directive Approach
<%@ OutputCache duration="3600" VaryByParam="ddlControl"%>
Programmatic Approach
Response.Cache.SetExpires(DateTime.Now.AddSeconds(3600));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.VaryByParams["ddlControl"] = true; |
|
Caching variations of a page at the server based upon strings:
Page Directive Approach
<%@ OutputCache duration="3600" VaryByParam="None" VaryByCustom="MyVersion""%>
Programmatic Approach
Response.Cache.SetExpires(DateTime.Now.AddSeconds(3600));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetVaryByCustom("MyVersion");
Note: The string, MyVersion, is actually replaced in the global.asax file by overriding method GetVaryByCustomString. For example:
public override string GetVaryByCustomString(HttpContext context, string arg) {
if (arg == "MyVersion") {
return "Version=" + SomeString;
}
return SomeOtherString;
} |
|
Caching variations of a page based upon browser type:
Page Directive Approach
<%@ OutputCache Duration="3600" VaryByHeader="User-Agent" VaryByParam="None" %>
Programmatic Approach
Response.Cache.SetExpires(DateTime.Now.AddSeconds(3600));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.VaryByHeaders["User-Agent"] = true; |
A High Performance Database Report
Assume your system resources are running low. You have determined that a majority of the problem is a database report that constantly runs with four different versions. You decide to implement server-side output caching so that each version of the report is only run once every hour.
STEP BY STEP
1. Add a new Web Form to your Visual Studio C# application.
2. Place a Label control (lblTimeLastGenerated), a DropDownList control (ddlCountry), a DataGrid control (dgReport), and a Button control (btnGetData) on the Web Form.
3. Select the Items property on the ddlCountry and then click the ellipsis (…) button. Add the following properties in the Collection Editor Dialog: France, Brazil, Italy, and Germany.
4. Now enter the following Page directive at the top of the Web Form’s HTML. This is the only line of code required for fragment caching.
<%@ OutputCache duration="3600" VaryByParam="ddlCountry" %>
Alternatively, use the HttpCachePolicy class in the code as follows:
Response.Cache.SetExpires(DateTime.Now.AddSeconds(3600));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);
Response.Cache.VaryByParams["ddlCountry"] = true;
5. Add the following code to the btnGetData button’s Click event handler in the code:
Listing 3 – Retrieving Database Reports
using System;
using System.Data.SqlClient;
private void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack == false)
GetData();
}
private void btnGetData_Click(object sender, EventArgs e)
{
GetData();
}
private void GetData()
{
SqlConnection conn = new SqlConnection(
"Data Source=(local); Initial Catalog=Northwind;" +
" Integrated Security=SSPI");
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = string.Format(
"SELECT * FROM customers WHERE Country = '{0}'",
ddlCountry.SelectedItem.Text);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
DataSet ds = new DataSet();
da.Fill(ds, "Customers");
dgReport.DataSource = ds;
dgReport.DataBind();
lblTimeLastGenerated.Text =
string.Format("Last generated {0}, {1}",
ddlCountry.SelectedItem.Text, DateTime.Now.ToString());
}
6. Run the web page from several different computers and you will notice the same time reported for each country. This is because the data is being retrieved from server cache.
Caching at the client and Proxy
Client and proxy caches can only store a single version of the web page. Therefore you will need to remove the drop down list and button controls. Leaving these controls will allow the user to re-request possibly updated content from the server. However, when the client revisits the page he will view the previously cached data. This could cause a lot of confusion.
Revisiting a page cached at the client will display the original time that the client visited the page. Unlike server cache, visiting the page from another computer will display an entirely new time.