SetETagFromFileDependencies—Enables you to set the ETag HTTP header from the time stamps of all files on which the page is dependent... SetLastModifiedFromFileDependencies—Enables you to
Trang 1<%= DateTime.Now.ToString(“T”) %>
<hr />
<asp:GridView
id=”grdMovies”
DataSourceID=”srcMovies”
Runat=”server” />
<asp:SqlDataSource
id=”srcMovies”
ConnectionString=”<%$ ConnectionStrings:Movies %>”
SelectCommand=”SELECT Title, Director FROM Movies”
Runat=”server” />
<br /><br />
<a href=”AddMovie.aspx”>Add Movie</a>
</div>
</form>
</body>
</html>
The page in Listing 29.12 contains a DetailsView control that enables you to add a new
movie When you insert a new movie into the database, the
Response.RemoveOutputCacheItem() method is called to remove the MovieList.aspx page
from the cache Because this method accepts only a “virtual absolute” path, the
Page.ResolveUrl() method converts the tilde into the application root path
LISTING 29.12 AddMovie.aspx
<%@ Page Language=”C#” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<script runat=”server”>
protected void dtlMovie_ItemInserted(object sender,
➥DetailsViewInsertedEventArgs e)
{
HttpResponse.RemoveOutputCacheItem(Page.ResolveUrl(“~/MovieList.aspx”));
Response.Redirect(“~/MovieList.aspx”);
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
Trang 2</head>
<body>
<form id=”form1” runat=”server”>
<div>
<h1>Add Movie</h1>
<asp:DetailsView
id=”dtlMovie”
DefaultMode=”Insert”
DataSourceID=”srcMovies”
AutoGenerateRows=”false”
AutoGenerateInsertButton=”true”
Runat=”server” OnItemInserted=”dtlMovie_ItemInserted”>
<Fields>
<asp:BoundField
DataField=”Title”
HeaderText=”Title:” />
<asp:BoundField
DataField=”Director”
HeaderText=”Director:” />
</Fields>
</asp:DetailsView>
<asp:SqlDataSource
id=”srcMovies”
ConnectionString=”<%$ ConnectionStrings:Movies %>”
InsertCommand=”INSERT Movies (Title, Director)
VALUES (@Title, @Director)”
Runat=”server” />
</div>
</form>
</body>
</html>
The Response.RemoveOutputCacheItem() method enables you to remove only one page
from the cache at a time If you need to remove multiple pages, you can create a key
dependency, which enables you to create a dependency between one item in the cache and
another item When the second item is removed from the cache, the first item is removed
automatically
For example, the page in Listing 29.13 also displays a list of movies However, the page is
cached with a dependency on an item in the cache named Movies
Trang 3LISTING 29.13 MovieListKeyDependency.aspx
<%@ Page Language=”C#” %>
<%@ OutputCache Duration=”3600” 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”>
protected void Page_Load(object sender, EventArgs e)
{
Cache.Insert(“Movies”, DateTime.Now);
Response.AddCacheItemDependency(“Movies”);
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Movie List Key Dependency</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<%= DateTime.Now.ToString(“T”) %>
<hr />
<asp:GridView
id=”grdMovies”
DataSourceID=”srcMovies”
Runat=”server” />
<asp:SqlDataSource
id=”srcMovies”
ConnectionString=”<%$ ConnectionStrings:Movies %>”
SelectCommand=”SELECT Title, Director FROM Movies”
Runat=”server” />
<br /><br />
<a href=”AddMovieKeyDependency.aspx”>Add Movie</a>
</div>
</form>
</body>
</html>
Trang 4The page in Listing 29.14 enables you to add a new movie to the Movies database table
When the new movie is inserted, the Movies item is removed, and any pages dependent
on the Movies item are dropped from the cache automatically
LISTING 29.14 AddMovieKeyDependency.aspx
<%@ Page Language=”C#” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<script runat=”server”>
protected void dtlMovie_ItemInserted(object sender,
➥DetailsViewInsertedEventArgs e)
{
Cache.Remove(“Movies”);
Response.Redirect(“~/MovieListKeyDependency.aspx”);
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Add Movie Key Dependency</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<h1>Add Movie</h1>
<asp:DetailsView
id=”dtlMovie”
DefaultMode=”Insert”
DataSourceID=”srcMovies”
AutoGenerateRows=”false”
AutoGenerateInsertButton=”true”
Runat=”server” OnItemInserted=”dtlMovie_ItemInserted”>
<Fields>
<asp:BoundField
DataField=”Title”
HeaderText=”Title:” />
<asp:BoundField
DataField=”Director”
HeaderText=”Director:” />
</Fields>
</asp:DetailsView>
Trang 5<asp:SqlDataSource
id=”srcMovies”
ConnectionString=”<%$ ConnectionStrings:Movies %>”
InsertCommand=”INSERT Movies (Title, Director)
VALUES (@Title, @Director)”
Runat=”server” />
</div>
</form>
</body>
</html>
Manipulating the Page Output Cache Programmatically
If you need more control over how ASP.NET Framework caches pages, then you can
work directly with the HttpCachePolicy class This class is exposed by the
Response.Cache property
The HttpCachePolicy class includes properties and methods that enable you to perform
programmatically all the tasks that you can perform with the <%@ OutputCache %>
direc-tive You also can use the methods of this class to manipulate the HTTP cache headers
that are sent to proxy servers and browsers
This class supports the following properties:
VaryByHeaders—Gets the list of headers that are used to vary cache output
VaryByParams—Gets the list of query string and form parameters used to vary cache
output
The HttpCachePolicy class also supports the following methods:
AddValidationCallback—Enables you to create a method called automatically before
a page is retrieved from the cache
AppendCacheExtension—Enables you to add custom text to the Cache-Control HTTP
header
SetAllowResponseInBrowserHistory—Enables you to prevent a page from appearing
in the browser history cache
SetCacheability—Enables you to set the Cache-Control header and the server
cache
SetETag—Enables you to set the ETag HTTP header
SetETagFromFileDependencies—Enables you to set the ETag HTTP header from the
time stamps of all files on which the page is dependent
Trang 6SetLastModified—Enables you to set the Last-Modified HTTP header
SetLastModifiedFromFileDependencies—Enables you to set the Last-Modified
HTTP header from the time stamps of all files on which the page is dependent
SetMaxAge—Enables you to set the Cache-Control:max-age HTTP header
SetNoServerCaching—Enables you to disable web server caching
SetNoStore—Enables you to send a Cache-Control:no-store HTTP header
SetNoTransform—Enables you to send a Cache-Control:no-transform HTTP header
SetOmitVaryStar—Enables you to not send the vary:* HTTP header
SetProxyMaxAge—Enables you to set the Cache-Control:s-maxage HTTP header
SetRevalidation—Enables you to set the Cache-Control HTTP header to either
must-revalidation or proxy-revalidate
SetSlidingExpiration—Enables you to set a sliding expiration policy
SetValidUntilExpires—Enables you to prevent a page from expiring from the web
server cache when a browser sends a Cache-Control header
SetVaryByCustom—Enables you to set the string passed to the
GetVaryByCustomString() method in the Global.asax file
For example, the page in Listing 29.15 programmatically places a page in the output
cache The page is cached on the browser, proxy servers, and web server for 15 seconds
LISTING 29.15 ProgramOutputCache.aspx
<%@ Page Language=”C#” %>
<!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()
{
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetExpires(DateTime.Now.AddSeconds(15));
Response.Cache.SetMaxAge(TimeSpan.FromSeconds(15));
Response.Cache.SetValidUntilExpires(true);
Response.Cache.SetLastModified(DateTime.Now);
Response.Cache.SetOmitVaryStar(true);
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Program OutputCache</title>
Trang 7</head>
<body>
<form id=”form1” runat=”server”>
<div>
<%= DateTime.Now.ToString(“T”) %>
<br /><br />
<a href=”ProgramOutputCache.aspx”>Request this Page</a>
</div>
</form>
</body>
</html>
Clearly, it is more difficult to enable Page Output Caching programmatically than
declara-tively You need to call many methods to cache a page in the same way as you can with a
single <%@ OutputCache %> directive However, programmatically manipulating the cache
provides you with fine-grained control over the HTTP headers sent to proxy servers and
browsers
Creating Page Output Cache Profiles
Instead of configuring Page Output Caching for each page in an application, you can
configure Page Output Caching in a web configuration file and apply the settings to
multiple pages You can create a Cache Profile Creating Cache Profiles makes your website
easier to manage
For example, the web configuration file in Listing 29.16 contains the definition for a
Cache Profile named Cache1Hour that caches a page for one hour
LISTING 29.16 Web.Config
<?xml version=”1.0”?>
<configuration>
<system.web>
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name=”Cache1Hour” duration=”3600” varyByParam=”none” />
</outputCacheProfiles>
</outputCacheSettings>
</caching>
</system.web>
</configuration>
Trang 8The page in Listing 29.17 uses the Cache1Hour profile This profile is set with the <%@
OutputCache %> directive’s CacheProfile attribute
LISTING 29.17 OutputCacheProfile.aspx
<%@ Page Language=”C#” %>
<%@ OutputCache CacheProfile=”Cache1Hour” %>
<!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>Output Cache Profile</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<%= DateTime.Now.ToString(“T”) %>
</div>
</form>
</body>
</html>
You can set the same caching properties in a Cache Profile as you can set in an individual
page’s <%@ OutputCache %> directive For example, you can set varyByParam,
varyByControl, varyByHeader, and even varyByCustom attributes in a Cache Profile
NOTE
ASP.NET 4 introduces a new feature called Extensible Output Caching, which enables
you to configure a custom output-cache provider that utilizes whatever storage medium
you choose—local disks, cloud-based storage, and so on To learn more about
develop-ing a custom output-cache provider, check out the MSDN website (http://msdn
microsoft.com)
Using Partial Page Caching
In the previous section of this chapter, you learned how to cache the entire output of a
page In this section, you learn how to take advantage of Partial Page Caching to cache
particular regions of a page
Partial Page Caching makes sense when a page contains both dynamic and static content
For example, you might want to cache a set of database records displayed in a page but
not cache a random list of news items displayed in the same page
Trang 9In this section, you learn about two methods for enabling Partial Page Caching You can
use post-cache substitution to cache an entire page except for a particular region You can
use User Controls to cache particular regions in a page, but not the entire page
Using Post-Cache Substitution
In some cases, you might want to cache an entire page except for one small area For
example, you might want to display the current username dynamically at the top of a
page but cache the remainder of a page In these cases, you can take advantage of a feature
of ASP.NET Framework called post-cache substitution.
Post-cache substitution is used internally by the AdRotator control Even when you use
Page Output Caching to cache a page that contains an AdRotator control, the content
rendered by the AdRotator control is not cached
You can use post-cache substitution either declaratively or programmatically If you want
to use post-cache substitution declaratively, you can use the ASP.NET Substitution
control For example, the page in Listing 29.18 uses the Substitution control to display
the current time on a page that has been output cached (see Figure 29.6)
FIGURE 29.6 Using the Substitution control.
Trang 10LISTING 29.18 SubstitutionControl.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”>
public static string GetTime(HttpContext context)
{
return DateTime.Now.ToString(“T”);
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Substitution Control</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
The cached time is: <%= DateTime.Now.ToString(“T”) %>
<hr />
The substitution time is:
<asp:Substitution
id=”Substitution1”
MethodName=”GetTime”
Runat=”server” />
</div>
</form>
</body>
</html>
In Listing 29.18, the time is displayed twice The time displayed in the body of the page is
output cached The time displayed by the Substitution control is not cached
The Substitution control has one important property: MethodName The MethodName
prop-erty accepts the name of a method defined in the page The method must be a shared
(static) method because an instance of the class is not created when the page is output
cached
Alternatively, you can use post-cache substitution programmatically by using the
Response.WriteSubstitution() method This method is illustrated in the page in
Listing 29.19