Here’s an easy way to dramatically improve performance and scalability of your ASP.NET Web applications: enable output caching. It takes less than one minute to enable caching on pages that aren’t personalized for individual users, such as news listings, search results and product catalogs. If your content is personalized or extremely time sensitive, you can significantly reduce ASP.NET rendering time with just a couple of hours of work.
Even the most dynamic sites can benefit from caching, through these techniques:
Server-side output caching is a quick and easy way to increase your Web application’s performance and scalability. Implementing caching in a typical Web application that includes some dynamic content can reduce processor utilization by 90 percent across all tiers of an application, including the front-end Web server, application servers and database servers. Because you control which portions of a page are cached and when the cache is updated, you can cache personalized pages and pages that display database queries without worrying about ever serving stale data. Maybe management could take some of the budget that they save on server upgrades and give the developers a raise!
With ASP.NET 2.0, you can enable server-side page output caching to store a copy of pages after ASP.NET has rendered them. If the same or a different user requests the page, ASP.NET serves the cached copy about as fast as it would serve static HTML because ASP.NET completely bypasses the rendering process.
To enable server-side page output caching, add the following directive to the top of your .aspx page:
<%@ OutputCache Duration="15" VaryByParam="none" %>
Notice that this example of the OutputCache directive includes the two required parameters:
Let’s say you have an ASP.NET page to browse your inventory by category, and a typical URL looks like this:
http://server/browse.aspx?category=widgets&page=1
Obviously, you wouldn’t want the output for the “widgets” category to be returned for the “gadgets” category, and each page number would have unique results, so you would use the following directive at the top of the browse.aspx page:
<%@ OutputCache Duration="15" VaryByParam="category; page" %>
This directive would cause ASP.NET to cache both pages 1 and 2 of the “widgets“ category separately, and rerender the page after 15 minutes. The “gadgets” and “widgets” categories would be cached separately, too. To create a separate cache for every parameter, set VaryByParam to “*”.
Many pages are personalized to show the user’s name, customized stock quotes or local ads. The directive described in the previous section would also cache personalized content, and cause it to be sent to the wrong users. To work around this, move any personalized content into .ascx user controls and add the “@ OutputCache” directive to the user controls (even if you simply need to disable caching for that control). ASP.NET will cache the user controls separately from the parent page and combine the cached output for every page that needs to be rendered. To disable output caching for a control, add the following directive to the top of the .ascx page:
<%@ OutputCache Duration="0" VaryByParam="none" %>
Instead of creating separate user controls for dynamic content, you may use substitution to dynamically generate HTML for parts of a page. To use substitution, follow these steps:
‘VB
Shared Function GetDate (ByVal context As HttpContext) As String
return DateTime.Now.ToString()
End Function
//C#
Public Static String GetDate (HttpContext context)
{
return DateTime.Now.ToString();
}
ASP.NET will automatically run the method you specify for the Substitution.MethodName parameter each time the page is requested, even if it uses the cached output for the rest of the page.
Thinking back to the example of using page output caching when browsing inventory by category, you might be able to tolerate new products not immediately appearing in cached pages, but you don’t have to. If you use Microsoft SQL Server 2005 on the back end, you may create a Structured Query Language database dependency that automatically invalidates the cache by setting OutputCache’s SqlDependency parameter to the value CommandNotification, demonstrated as follows:
<%@ OutputCache SqlDependency="CommandNotification" Duration="15" VaryByparam="none" %>
SQL Server 2005 will automatically notify ASP.NET if the results of any queries used in the page have changed, and ASP.NET will rerender the cached page on the next request. For information about how to create queries that support query notification, read “Creating a Query for Notification” at http://msdn2.microsoft.com/en-US/library/ms181122.aspx [2]. If any of your queries don’t support notification (for example, if you used “SELECT *”), no caching will occur.
If you use Microsoft SQL Server 7.0 or Microsoft SQL Server 2000, you may achieve similar functionality by configuring the database using the Aspnet_RegSql.exe command (in your “%windir%\Microsoft.NET\Framework\<build>\” folder) to set up the database and table to support dependencies. For more information, read “Improved Caching in ASP.NET 2.0” at http://msdn2.microsoft.com/en-us/library/ms379559(VS.80).aspx [3].
If you would rather run code to determine whether to use the cached version of a page or rerender it, you may create an HttpCacheValidateHandler for the cached page and set the HttpValidationStatus parameter to one of the following three values:
The following code demonstrates how to handle the event:
‘VB
Public Shared Sub ValidateCache (ByVal context As HttpContext, _
ByVal data As [Object], ByRef status As HttpValidationStatus)
‘ TODO: Add logic to set one of the following values
status = HttpValidationStatus.Invalid
status = HttpValidationStatus.IgnoreThisRequest
status = HttpValidationStatus.Valid
//C#
public static void ValidateCache (HttpContext context,
Object data, ref HttpValidationStatus status)
{
// TODO: Add logic to set one of the following values
status = HttpValidationStatus.Invalid
status = HttpValidationStatus.IgnoreThisRequest
status = HttpValidationStatus.Valid
}
After creating the method, define it as the event handler in the Page_Load method:
‘VB
Protected Sub Page_Load (ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
Response.Cache.AddValidationCallback ( _
New HttpCacheValidateHandler (AddressOf ValidateCache), Nothing)
//C#
protected void Page_Load (object sender, EventArgs e)
{
Response.Cache.AddValidationCallback (
new HttpCacheValidateHandler (ValidateCache), null);
}
Links:
[1] http://www.biztechmagazine.com/author/tony-northrup
[2] http://msdn2.microsoft.com/en-US/library/ms181122.aspx
[3] http://msdn2.microsoft.com/en-us/library/ms379559(VS.80).aspx