When you enable output caching on a given page, the page's response will be cached for a specified time so that successive requests can be served without executing the code behind the page. This simple trick transforms the original ASP.NET page in something close to a static HTML page as far as performance is concerned.
Output caching is flexible enough to let you store distinct versions of the page per each combination of HTTP headers or query string parameters. The output of the page can be cached on the Web server, the client, or any proxy server downstream such as Microsoft ISA Server. The caching location is just one of the parameters you can set when you configure output caching for a page.
|True visual inheritance as in Windows Forms is not a goal of ASP.NET 2.0 master pages. The contents of a master page are merged into the content page, and they dynamically produce a new page class. The merge process takes place at compile time and only once.|
To cache the whole page you simply add the @OutputCache
directive on top of the page. This is not the only option you have, though. If needed, you modify the cacheable regions of your page to be rendered through a user control and configure the user control to support output caching. These are the two options you have as of ASP.NET 1.x. What happens if you want to cache everything on the page except for a few regions? In ASP.NET 2.0 you can do this as well thanks to post-cache substitution. For example, using this mechanism, an AdRotator control can serve a different advertisement on each request even if the host page is cached.
To use post-cache substitution, you place the new <asp:substitution>
control at the page location where content should be substituted and set the MethodName
property of the control to a callback method. Here's a quick example.
<form id="form1" runat="server">
<h3>The output you see has been generated at:
and is valid for 30 seconds</h3>
This content is updated regularly
This is more static and cached content
<asp:Button runat="server" Text="Refresh" />
You must set the MethodName
property to the name of a static method that can be encapsulated in an HttpResponseSubstitutionCallback
public static string WriteTimeStamp(
Whatever string the method returns will be rendered out and becomes the output of the Substitution control. Note also that the callback method must be thread-safe and static.
Using post-cache substitution automatically disables client caching and forces the page to use server caching. This is reasonable as the markup replacement can only happen through server-side code. The page can't rely on IIS 6.0 kernel mode caching and its benefits. Again, this is reasonable as some server-side work is required to serve the page. In light of this, the page can't be served by IIS without hitting ASP.NET. Finally, note that the Substitution control works even if the page doesn't use page output caching. In the end, Substitution is a mere server-side control and is processed as usual. In a non-cached page, your callback will be called at rendering time to contribute to the response.
More important than ever, you should avoid calling the substitution control from within the callback. If you do so, the callback will hold on to the control and the page containing the control. In the end, the page instance won't be garbage-collected until the cached content expires.
#5The Provider Model
The provider model is one of the most important and critical aspects of ASP.NET 2.0. A comprehensive understanding of the provider model is critical for an effective design and implementation of cutting edge applications. The provider model is formalized in ASP.NET 2.0 but, at the end of the day, it is the implementation of the strategy
design pattern-a software feature not strictly related to .NET and ASP.NET. Once you get hold of the basic idea, you can start using the provider model in any application. In particular, you can (and to some extent, you should) use it to architect your own ASP.NET 2.0 applications.
Defined, the strategy
pattern indicates a behavior and the strategy you intend to use to implement it. As an example, consider the behavior of sorting data. You can sort data through an array of algorithms such as Quicksort
or perhaps Mergesort
. Each sort algorithm represents a different, but equally valid, strategy. Whatever strategy you choose, the observable behavior of the code remains intact-that is, the code still sorts its data.
The most notable feature of the strategy pattern is that it provides a way for a subsystem to expose its internal plumbing so that a client can unplug the default implementation and plug its own in.
This is exactly what happens in ASP.NET 2.0 for a number of services, including membership, roles, state management, personalization, and site maps. The ASP.NET provider model is nothing more than the ASP.NET implementation of the strategy pattern.
The best thing you can do in your own applications is devise each feature that needs to read data from or write data to a data source according to the strategy pattern. You define a public and immutable programming interface and make your top-level code interact only with that. Such a programming interface is well-represented with a static class exposing a bunch of public methods. Under the hood, each method will locate the current strategy class providing the requested behavior. How the strategy class is located and the details of the programming interface are entirely up to you.
If you're doing this in ASP.NET 2.0, you might want to derive strategy classes (i.e., providers) from the official base provider class-ProviderBase. All provider classes in ASP.NET inherit from ProviderBase. This is not a functionally rich class so you might want to create an intermediate class named MyFeatureProviderBase or something like that, and make this class extend ProviderBase with the programming interface you need for the specified feature. Trust me, this is easier done than explained and will give you unprecedented geek pleasure.
#6Session Data Stores
In ASP.NET, you can store session state in a variety of places that you can configure offline through the web.config file. By default, the session state is held in the Web server's memory, precisely in the Cache object. Alternately, you can ask the ASP.NET runtime to store session state in the memory of a remote server or in a made-to-measure SQL Server database.
Most developers tend to forget the implications of storing session data out-of-process. There are two types of possible implications: data marshaling and configuration.
If session data is managed by a process different from the ASP.NET worker process, the application has to pay the extra price of marshaling data from the external process to the worker process. The ASP.NET infrastructure has to read, marshal, and process data.
The cost of reading data is merely the cost of I/O. This cost is higher if a system file, like a database file, is involved. The cost of data marshaling is the cost of serializing data using the .NET Framework formatter classes. The cost of processing data is any cost involved with copying the session state from the external source to the HTTP context of the ongoing request.
In ASP.NET 1.x, you can store data outside the worker process in either of two ways: state server and SQL Server. In the former case, data is managed by a Windows service (aspnet_state.exe) that requires manual start and runs under the ASP.NET process account. The communication between ASP.NET and this process occurs through a fixed port over TCP. The data is stored in the memory of the state process and is subject to any failure of the service. The cost of I/O is minimal just because data lives in memory. If SQL Server is used, data is stored in a persistent database with a higher I/O cost.
Data is serialized back and forth using type-specific algorithms. Simple data types such as numbers, strings, dates, characters, bytes, and arrays of these types are serialized using a tailor-made serializer that optimizes the time required to save data of those types. Other types are first checked for a type converter class-a class that can convert the contents of the class into a string. If no type converter is found, the class is serialized using the .NET Framework binary formatter class. If the class is not serializable, an exception is thrown. The binary formatter is the most efficient formatter available, but is not all that fast compared to other techniques that can be used to serialize the contents of a class. The reason lies in the fact that the binary formatter is designed to service any managed class handling complex scenarios such as circular references. A formatter specifically designed for a limited group of classes can easily outperform the binary formatter. What's the lesson?
When remote session state is enabled, you should avoid using complex data types such as DataSet or custom classes. The more you can resort to strings and numbers, the better performance you'll see. To give evidence to the discussion, consider a 15 percent overhead if you connect to a state server and a 25 percent overhead if you use a database table to store the session state. If binary serialization is required, expect to see these numbers rise a little more.
The trade-off here is clear: speed versus robustness. If you're looking for extreme robustness-for example, the capability of surviving IIS crashes-consider the following, additional issues.
You need a machine (not necessarily the local Web server machine) that contains an installation of SQL Server 7.0 or any newer version. You have to buy a SQL Server license if you don't already have one. This might be good for Microsoft, but not necessarily for you or your client. If your application, say, is based on Oracle or DB2, couldn't you simply store your session state to a database in the DBMS of choice? The answer is a disappointing no in ASP.NET 1.x, but a resounding yes in ASP.NET 2.0!
In ASP.NET 2.0, you can create a custom session data store that, according to the provider model, plugs into a common infrastructure and API and implements data storage and retrieval on top of the file system, a custom DBMS, or a customized table in SQL Server. In ASP.NET 2.0, the session state subsystem has been refactored to allow developers to replace most of the functionality. You have the following options to customize session state management.
- You can stay with the default session state module but write a custom state provider to change the storage medium (e.g., a non-SQL Server database or a different table layout). In doing so, you can also override some of the collection classes used to bring data from the store to the Session object and back.
- You can stay with the default session state module but replace the session ID generator.
- You can unplug the default session state HTTP module and install your own. Technically this was possible in ASP.NET 1.x but this option is the last you should consider. Obviously, it provides the maximum flexibility but it is also extremely complicated and thus not recommended unless it proves strictly necessary.
Using a database as the session state data store also poses configuration issues, especially in ISP scenarios. The SQL Server environment needs to be extended to accommodate a new database and its tables, stored procedures, and related jobs. For this task, administrative privileges are required or the collaboration of the DBA.
In ASP.NET 1.x, credentials used to access session state stored in SQL Server depend on the connection string. If explicitly provided, user name and password will be used to access the database. Otherwise, if integrated security is requested, the account of the currently logged in client is used. This approach poses some administrative issues for intranet sites using client impersonation. In these cases, in fact, you have to grant access to the database to every client account that might be making calls. In ASP.NET 2.0, you can configure the session state so that the identity used to access SQL Server corresponds to the account running the ASP.NET worker process. This new optional behavior for SQL Server-based session state is consistent with the behavior of the other remote state server-the one using the Windows service.