Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Take Advantage of ASP.NET 2.0's Data Caching Techniques, Part 1 : Page 3

This two-part article shows you how to take advantage of the many ways that you can boost the performance of ASP.NET applications by caching the data they use. Although some of the techniques apply to both ASP.NET 1.0 and 2.0, the new capabilities in ASP.NET 2.0 make caching even more attractive for busy Web sites.

Caching Data as a String
A useful point to keep in mind whenever you store data that is not a string value, especially when you are dealing with more complex classes that persist their data internally (such as a DataSet), is that most support a method to export the content as a string. For example, with a DataSet (and, in version 2.0, a DataTable), you can use the WriteXml method to write the data as an XML document, which is itself just a text string. You can also provide the writeMode parameter (a value from the XmlWriteMode enumeration) that specifies if a schema is included, and whether you want a simple XML representation of the data or a diffgram that stores change information as well.

The following code shows how to serialize a DataSet as an XML document and store it in the ViewState of the page, and then re-instantiate the DataSet for each postback:

Imports System.IO ' needed to use StringWriter Dim dsMyData As New DataSet() If Page.IsPostBack Then Dim reader As New _ StringReader(CStr(ViewState("MyDataSet"))) dsMyData.ReadXml(reader) Else '... code to fill DataSet from source data store here ... Dim writer As New StringWriter() dsMyData.WriteXml(writer) ViewState("MyDataSet") = writer.ToString() End If

Figure 1. DataSet XML Persistance: When you first load this page, it reads the DataSet data from a database, storing the DataSet as XML in the ViewState, but subsequent page refreshes reconstitute the DataSet from the XML representation in the ViewState rather than reloading it from the database.
Author's Note: See the .NET Framework SDK topic "StringWriter Members" in the "Reference | Class Library" section for more details.

The downloadable sample code for this article contains an example of caching the contents of a DataSet as an XML string value within the page ViewState. The write-ViewState.aspx example uses the code listed above. The result looks like Figure 1. When the server loads the first page, it fetches the data from the database; however, as you refresh the page, it rebuilds the DataSet each time from the XML cached in the ViewState.

Caching Data as a Disk File
The .NET Framework provides plenty of easy-to-use classes for reading and writing disk files. You can use these when you need to cache data required for more than one ASP.NET application. As an example, suppose you want to cache a DataSet containing data to which all the applications on your server require access. You could capitalize on the just-described technique for calling the WriteXml and ReadXml methods, which work automatically with a disk file—all you have to do is provide the path and filename.

However, you can also use a BinaryFormatter to write data from objects that are serializable to a Stream. The code below demonstrates using a FileStream with a DataSet, but you could just as easily cache the data in memory using a MemoryStream if required. Why bother with binary serialization when the DataSet can serialize itself as XML? Well, the one extra feature here revolves around the fact that, in version 2.0, the DataSet gains a new property named RemotingFormat. This can be set to a value from the SerializationFormat enumeration (the two options are Xml or Binary). When set to Binary, the volume of data generated from a DataSet is generally reduced by between 20 and 80 percent, which results in smaller disk files, faster loading, and ultimately better performance:

' create BinaryFormatter and Stream Dim f As IFormatter = New BinaryFormatter() Using s As New FileStream(datPath, _ FileMode.Create, FileAccess.Write, FileShare.None) ' specify Binary remoting format for the DataSet ' (new in v 2.0) dsMyDataSet.RemotingFormat = SerializationFormat.Binary ' serialize the contents to the Stream as binary data f.Serialize(s, dsMyDataSet) s.Close() End Using

To rebuild the DataSet from the disk file, you can use this code:

' now de-serialize the data back into a new DataSet Dim dsMyDataSet As DataSet Dim f As IFormatter = New BinaryFormatter() Using s As New FileStream(datPath, FileMode.Open, FileAccess.Read, FileShare.Read) ' de-serialize file contents into a DataSet dsMyDataSet = CType(f.Deserialize(s), DataSet) s.Close() End Using

Figure 2. DataSet Serialization: The figure illustrates the process of serializing a DataSet to a disk File and later deserializing it back into a DataSet.
Author's Note: The preceding code takes advantage of the Using construct, which was available in C# in v1.1 and is now available in VB.NET in v 2.0.

Figure 2 shows the provided example (serialize-to-disk.aspx) that uses this code to serialize a DataSet to a disk file, and then de-serialize it back into a DataSet again. The page also displays some rows from the DataSet to prove that it worked.

Many objects support the ISerializable interface, and so can be used with a BinaryFormatter as shown above (though the actual format of the persisted data will vary with the object type). Suitable classes include collection types such as HashTable and NameValueCollection, the ADO.NET DataSet and DataTable, and the Image class that is used to create and store bitmap images.

Author's Note: See the .NET Framework SDK topic "BinaryFormatter Members" in the "Reference | Class Library" section for more details.

ASP.NET Output Caching
One extremely useful way to boost performance in ASP.NET is to avoid running server-side script to provide a new version of the page for each request. To do that, you can use output caching, which is useful when users regularly or repeatedly load the same page. ASP.NET implements output caching internally, so it's seamless for developers. By specifying a directive in the ASP.NET page, the server automatically caches the HTML generated by the page according to the conditions you specify.

The simplest output caching directive is:

<%@OutputCache Duration="#seconds" VaryByParam="None" />

The preceding line instructs ASP.NET to cache the HTML for the specified number of seconds, irrespective of the parameters sent with the page request from the client. "Parameters" in this sense means any values in the Request collections (Form, QueryString, Cookies, and ServerVariables). While the page is cached, every request will return the HTML generated the last time that the page was executed being sent to the client. In IIS 6.0, in Windows Server 2003, this detection of cached pages is actually done inside the kernel-level HTTP redirector module, and so it is blindingly fast—quicker than in IIS 5.0 and, of course, a great deal faster that re-executing the page.

There are many alternative ways to configure output caching in ASP.NET. The OutputCache directive provides a range of options, for example:

<%@ OutputCache Duration="#seconds" Location="[Any|Client|Downstream|Server|None]" Shared="[true|false]" VaryByControl="control-name(s)" VaryByParam="[None|*|parameter-name(s)]" VaryByHeader="header-name(s)" VaryByCustom="[Browser|custom-string"] %>

Table 2 defines the attribute values used above.

Table 2. OutputCache Directive Attributes: The table lists the attributes you can use to fine-tune the OutputCache directive.
Attribute Description
Duration Required in every ASP.NET OutputCache directive. The number of seconds that the generated HTML will be cached.
Location Defines if page output can be cached on a proxy or downstream client. Often omitted, so that caching is performed in the most efficient way. However, it is a good idea to include Location="Any" where you do not actually need to control the location.
Shared Used only in a User Control. Defines if multiple instances of the control will be served from one cached instance. If False (the default) multiple instances will be cached.
VaryByControl Used only in a User Control. Declares the ID of ASP.NET controls that the cache will be varied by. For example: VaryByControl="MyTextBox;MyListBox" will cause a new version of the page to be cached for each differing value in the specified controls within the user control.
VaryByParam Required in every ASP.NET OutputCache directive. Defines the names of the parameters that will be used to determine if a cached version of the page will be delivered. For example: VaryByParam="txtName;lstSelection" will cause a new version of the page to be cached for each differing value in the QueryString, Form, Cookies or ServerVariables collections that has one of the specified names.
VaryByHeader The name(s) of any HTTP Header(s) that are used to determine if a cached version of the page will be delivered. For example: VaryByHeader="USER-AGENT;SERVER;REMOTE-HOST"
VaryByCustom The special value "Browser" specifies that the cached version of the page will only be delivered to browsers with the same name and major version: VaryByCustom="Browser". Alternatively, you can place a custom function in global.asax that returns a String value based on some criteria you require, and the page will be varied for each client that causes a different value to be returned. For example: VaryByCustom="MyGlobalFunction" (see the following note for an example of this).

Author's Note: Remember that ASP.NET varies the HTML it generates based on the browser type ("uplevel"—meaning Internet Explorer 5 and above; or "downlevel"—meaning all the rest). Therefore you might want to consider including the VaryByCustom="Browser" attribute if your page uses ASP.NET controls that can generate browser-specific output. Examples are controls such as Menu and Panel. The way that ASP.NET specifies style information for most other Web Forms controls also changes depending on the browser type, and may affect the appearance. You can experiment with these effects using a sample page from the book "Pro ASP.NET 1.1 Web Forms Techniques", see: http://www.daveandal.net/books/7868/control-compatibility/default.aspx . The asp-cache-by-level option shows how you can implement custom "vary by" functions. I've included the function code within the downloadable code samples for this article.

Figure 3. Output Caching: The figure illustrates how the VaryByParam="*" attribute affects output caching.
You can use the example page named output-cache-params.aspx (see Figure 3) to experiment with output caching. As the VaryByParam attribute is set to "*", all the controls on the page will invalidate the cached HTML copy, and so changing the value in any one will cause the page to be re-executed (the time it was last executed is shown in the page). However, refreshing the page within the 10-second cache duration period specified in the OutputCache directive does not cause it to be re-executed.

One interesting point demonstrated in this example is that using the ASP.NET auto-postback feature causes the page to be re-executed more than once. For example, changing the value in the second drop-down list initiates a postback automatically. And, because the values in the controls have changed, ASP.NET invalidates the cache and re-executes the page. However, if you then click the Refresh button, it executes the page again—rather than serving it from the output cache. This is because the name and caption of the button are included in the parameters posted back to this page when the button is clicked, whereas they are not included when the postback is caused by the drop-down list that has the AutoPostback="True" setting.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date