ptg This page intentionally left blank From the Library of Wow! eBook ptg CHAPTER 29 Caching Application Pages and Data IN THIS CHAPTER . Overview of Caching . Using Page Output Caching . Using Partial Page Caching . Using DataSource Caching . Using Data Caching . Using SQL Cache Dependencies . Summary The slowest operation that you can perform in an ASP.NET page is database access. Opening a database connection and retrieving data is a slow operation. The best way to improve the performance of your data access code is not to access the database at all. By taking advantage of caching, you can cache your data- base records in memory. Retrieving data from a database is slow. Retrieving data from the cache, on the other hand, is lightning fast. In this chapter, you learn about the different caching mech- anisms supported by ASP.NET Framework, which provides you with an overwhelming number of caching options. We attempt to clarify all these caching options over the course of this chapter. In the final section of this chapter, you learn how to use SQL Cache Dependencies, which enable you to reload cached data automatically when data changes in a database table. You learn how to use both polling and push SQL Cache Dependencies. Overview of Caching The ASP.NET 4 Framework supports the following types of caching: . Page Output Caching . Partial Page Caching . DataSource Caching . Data Caching From the Library of Wow! eBook ptg 1336 CHAPTER 29 Caching Application Pages and Data Page Output Caching enables you to cache the entire rendered contents of a page in memory (everything that you see when you select View Source in your web browser). The next time that any user requests the same page, the page is retrieved from the cache. Page Output Caching caches an entire page. In some situations, this might create prob- lems. For example, if you want to display different banner advertisements randomly in a page, and you cache the entire page, the same banner advertisement displays with each page request. NOTE The AdRotator control included in ASP.NET Framework takes advantage of a feature called post-cache substitution to randomly display different advertisements even when a page is cached. Post-cache substitution is described later in this chapter. Partial Page Caching enables you to get around this problem by enabling you to cache only particular regions of a page. By taking advantage of Partial Page Caching, you can apply different caching policies to different areas of a page. You use DataSource Caching with the different ASP.NET DataSource controls such as the SqlDataSource and ObjectDataSource controls. When you enable caching with a DataSource control, the DataSource control caches the data that it represents. Finally, Data Caching is the fundamental caching mechanism. Behind the scenes, all the other types of caching use Data Caching. You can use Data Caching to cache arbitrary objects in memory. For example, you can use Data Caching to cache a DataSet across multiple pages in a web application. In the following sections, you learn how to use each of these different types of caching in detail. NOTE Caching LINQ to SQL queries raises special issues, which are addressed in Chapter 20, “Data Access with LINQ to SQL.” NOTE When configuring and debugging caching, having a tool that enables you to monitor the HTTP traffic between web server and browser is extremely helpful. You can download the free Fiddler tool, which enables you to view the raw request and response HTTP traffic, from http://www.FiddlerTool.com. From the Library of Wow! eBook ptg 1337 Using Page Output Caching Using Page Output Caching You enable Page Output Caching by adding an <%@ OutputCache %> directive to a page. For example, the page in Listing 29.1 caches its contents for 15 seconds. LISTING 29.1 CachePageOutput.aspx <%@ Page Language=”C#” %> <%@ OutputCache Duration=”15” VaryByParam=”none” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <script runat=”server”> void Page_Load() { lblTime.Text = DateTime.Now.ToString(“T”); } </script> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Cache Page Output</title> </head> <body> <form id=”form1” runat=”server”> <div> <asp:Label id=”lblTime” Runat=”server” /> </div> </form> </body> </html> The page in Listing 29.1 displays the current server time in a Label control. The page also includes an <%@ OutputCache %> directive. If you refresh the page multiple times, you notice that the time is not updated until at least 15 seconds have passed. 29 From the Library of Wow! eBook ptg 1338 CHAPTER 29 Caching Application Pages and Data When you cache a page, the contents of the page are not regenerated each time you request the page. The .NET class that corresponds to the page is not executed with each page request. The rendered contents of the page are cached for every user that requests the page. The page is cached in multiple locations. By default, the page is cached on the browser, any proxy servers, and on the web server. In Listing 29.1, the page is cached for 15 seconds. You can assign a much larger number to the duration attribute. For example, if you assign the value 86400 to the duration parame- ter, the page is cached for a day. NOTE There is no guarantee that a page will be cached for the amount of time that you specify. When server memory resources become low, items are automatically evicted from the cache. Varying the Output Cache by Parameter Imagine that you need to create a separate master and details page. The master page displays a list of movies. When you click a movie title, the details page displays detailed information on the movie selected. When you create a master/details page, you typically pass a query string parameter between the master and details page to indicate the particular movie to display in the details page. If you cache the output of the details page, however, everyone will see the first movie selected. You can get around this problem by using the VaryByParam attribute. The VaryByParam attribute causes a new instance of a page to be cached when a different parameter is passed to the page. (The parameter can be either a query string parameter or a form parameter.) For example, the page in Listing 29.2 contains a master page that displays a list of movie titles as links. LISTING 29.2 Master.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Master</title> </head> <body> From the Library of Wow! eBook ptg 1339 Using Page Output Caching <form id=”form1” runat=”server”> <div> <asp:GridView id=”grdMovies” DataSourceID=”srcMovies” AutoGenerateColumns=”false” ShowHeader=”false” GridLines=”none” Runat=”server”> <Columns> <asp:HyperLinkField DataTextField=”Title” DataNavigateUrlFields=”Id” DataNavigateUrlFormatString=”~/Details.aspx?id={0}” /> </Columns> </asp:GridView> <asp:SqlDataSource id=”srcMovies” ConnectionString=”<%$ ConnectionStrings:Movies %>” SelectCommand=”SELECT Id,Title FROM Movies” Runat=”server” /> </div> </form> </body> </html> If you hover your mouse over the links displayed in Listing 29.2, you can see the query string parameter passed by each link in the browser status bar (see Figure 29.1). For example, the first movie link includes a query string parameter with the value 1, the second link includes a query string parameter with the value 2, and so on. When you click a movie link, this query string parameter is passed to the details page in Listing 29.3. 29 From the Library of Wow! eBook ptg 1340 CHAPTER 29 Caching Application Pages and Data LISTING 29.3 Details.aspx <%@ Page Language=”C#” %> <%@ OutputCache Duration=”3600” VaryByParam=”id” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Details</title> </head> <body> <form id=”form1” runat=”server”> <div> <%= DateTime.Now.ToString(“T”) %> <hr /> <asp:DetailsView id=”dtlMovie” DataSourceID=”srcMovies” Runat=”server” /> FIGURE 29.1 Displaying the Master page. From the Library of Wow! eBook ptg 1341 Using Page Output Caching <asp:SqlDataSource id=”srcMovies” ConnectionString=”<%$ ConnectionStrings:Movies %>” SelectCommand=”SELECT * FROM Movies WHERE Id=@Id” Runat=”server”> <SelectParameters> <asp:QueryStringParameter Name=”Id” Type=”int32” QueryStringField=”Id” /> </SelectParameters> </asp:SqlDataSource> </div> </form> </body> </html> The page in Listing 29.3 uses a DetailsView to display detailed information on the movie selected from the master page (see Figure 29.2). The DetailsView is bound to a SqlDataSource control that includes a QueryStringParameter SELECT parameter that represents the id query string parameter. 29 FIGURE 29.2 Displaying the Details page. From the Library of Wow! eBook ptg 1342 CHAPTER 29 Caching Application Pages and Data The Details.aspx page includes an <%@ OutputCache %> directive. The VaryByParam attribute in the <%@ OutputCache %> directive has the value id. If you request the Details.aspx page with a different value for the id query string parameter, a different cached version of the page is created. It is important to understand that using VaryByParam results in more caching and not less caching. Each time a different id parameter is passed to the Details.aspx page, another version of the same page is cached in memory. The Details.aspx page displays the current time. The time does not change when you request the Details.aspx page with the same query string parameter. You can assign two special values to the VaryByParam attribute: . none—Causes any query string or form parameters to be ignored. Only one version of the page is cached. . *—Causes a new cached version of the page to be created whenever there is a change in any query string or form parameter passed to the page. You also can assign a semicolon-delimited list of parameters to the VaryByParam attribute when you want to create different cached versions of a page, depending on the values of more than one parameter. Varying the Output Cache by Control The VaryByControl attribute enables you to generate different cached versions of a page depending on the value of a particular control in the page. This attribute is useful when you need to create a single-page Master/Details form. For example, the page in Listing 29.4 contains both a DropDownList and GridView control. When you select a new movie category from the DropDownList, a list of matching movies displays in the GridView (see Figure 29.3). From the Library of Wow! eBook ptg 1343 Using Page Output Caching LISTING 29.4 MasterDetails.aspx <%@ Page Language=”C#” %> <%@ OutputCache Duration=”3600” VaryByControl=”dropCategories” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Master/Details</title> </head> <body> <form id=”form1” runat=”server”> <div> <%= DateTime.Now.ToString(“T”) %> <hr /> <asp:DropDownList id=”dropCategories” DataSourceID=”srcCategories” DataTextField=”Name” DataValueField=”Id” Runat=”server” /> 29 FIGURE 29.3 Displaying a single-page Master/Details form. From the Library of Wow! eBook . polling and push SQL Cache Dependencies. Overview of Caching The ASP. NET 4 Framework supports the following types of caching: . Page Output Caching . Partial Page Caching . DataSource Caching CHAPTER 29 Caching Application Pages and Data LISTING 29.3 Details.aspx <%@ Page Language=”C#” %> <%@ OutputCache Duration=”3600” VaryByParam=”id” %> <!DOCTYPE html PUBLIC -/ /W3C//DTD. Wow! eBook ptg 1337 Using Page Output Caching Using Page Output Caching You enable Page Output Caching by adding an <%@ OutputCache %> directive to a page. For example, the page in Listing