ASP.NET 2.0 Internals

yelpframeSecurity

Nov 4, 2013 (3 years and 11 months ago)

106 views

ASP.NET 2.0 Internals




Jayesh Patel, Bryan Acker, Robert McGovern

Infusion Development

March 2005

Applies to:


Microsoft ASP.NET 2.0

Summary:
While 100 percent backward compatible with ASP.NET 1.1, ASP.NET 2.0
brings a number of internal changes to AS
P.NET. These include changes to the code
model, compilation, page lifecycle, and more. This article outlines those changes.

(21 printed pages)

Contents

Introduction

Code Model

Compilation

Full Runtime Compilation (The Code Directory)

Page Lifecycle

Extensibility

Advanced Caching Techniques

Performance

Conclusion

Introduction

For professional ASP.NET developers, the big questions about ASP.
NET 2.0 relate to
what has changed on the inside. New features are fun and interesting to learn about,
but changes to the core structure of ASP.NET speak louder to developers who really
want to master the technology. In this white paper, we will cover how
the internal
structure of ASP.NET 2.0 has changed since version 1.
x
.

The topics covered in this paper will be of use to performance
-
minded developers
and technical architects seeking to fine
-
tune applications. Specifically, we will
examine key areas of th
e code model, compilation, page lifecycle, extensibility,
performance, and caching.

Many examples in this document require considerable familiarity with ASP.NET,
Visual Basic .NET, and/or C# syntax. Where applicable, reference documents have
been provided
for in
-
depth discussion on particular subjects.

Code Model

Perhaps the most obvious change in the internal workings of ASP.NET 2.0 relates to
how an ASP.NET Web page is created. In this section, we will examine the changes
to the code
-
behind model and how
these changes impact ASP.NET development.

Coding Models in ASP.NET 1.
x

In ASP.NET 1.
x
, developers had two primary options for developing a Web Form.
First, the developer could follow the traditional ASP model and write code directly in
the ASPX page. This
process, known as
code
-
inline,
works very well for simple
commands. However, for more complex code, writing code
-
inline results in difficult
to read Web pages that mix presentation (HTML) with functionality (code).

In ASP.NET, the default coding practice
was changed to help solve this problem.
Business logic and event
-
handling code could be written in a separate, code
-
only file
known as the
code
-
behind
file. The code
-
behind model links a code
-
only file with the
ASPX file that contains presentation tags. B
y separating the code from the
presentation, development teams could work faster by allowing the designers to
work on the presentation file while the developers worked on the code file.


Figure 1. ASP.NET 1.
x
coding model

The primary difficulties with the code
-
behind model related to the way in which the
code
-
behind file had to be synchronized with the ASPX page. Although the ASPX
page inherited
from the code
-
behind file in a programming sense, the two files were
actually coupled by a more complex relationship.

For more detailed information on the code
-
behind model in ASP.NET 1.
x
, see the
MSDN Library article,
Web Forms Code Model
.

Inheritance Complexity

The design paradigm for ASP.NET was that developers would use Microsoft Visual
Studio .NET to drag an
d drop controls onto the ASPX page. Visual Studio would then
automatically generate the appropriate supporting code in the code
-
behind file. If
controls were added to the ASPX page, new code had to be added to the code
-
behind
file. In other words, despite
the inheritance relationship pointing the other way, the
ASPX page actually drove the design of the code
-
behind file.

Compilation Complexity

The second synchronization problem was in the way that the files were compiled. All
of the code
-
behind files, along
with any supporting classes, were compiled into an
assembly and stored in the
/bin
directory of the Web application. The compilation
step occurred prior to deploying the application. On the other hand, the ASPX page
was compiled at runtime the first time
the page was requested. The ASP.NET
runtime actually compiled the ASPX page into its own temporary assembly.

The problem with this process is that the ASPX page can be changed without
updating the code
-
behind assembly. That is, a developer may choose to m
odify a
property or change the
type
of a control on an ASPX page after deployment, and the
code
-
behind file would not be updated, nor would the application assembly be
recompiled. When this happened, the application would suffer unexpected errors
because o
f the mismatch between code
-
behind files and their associated ASPX
pages.

Coding Models in ASP.NET 2.0

ASP.NET 2.0 continues to offer both the code
-
inline and code
-
behind coding models.
In terms of the code
-
inline model, very little has changed except for
the way that
Microsoft Visual Studio 2005 supports single
-
file development. For more details on
changes in Visual Studio 2005 and how it handles code
-
inline, see
this article
.

ASP.NET 2.0 addresses both the inheritance and compilation concerns of the code
-
behind model by modifying the nature of the code
-
behind file. In ASP.NET 2.0, the
code
-
behind file is no longer
a full implementation of the
System.Web.UI.Page
class. Instead, the code
-
behind file is a new construct called a
partial class
. The
partial class contains all of the user
-
defined code, but omits all of the plumbing and
connectivity code that was auto
-
gene
rated by Visual Studio .NET in ASP.NET 1.
x
.
When an ASPX page with a new code
-
behind file is requested, the ASP.NET 2.0
runtime will actually combine the ASPX page and the partial class into a single class,
rather than two separate classes.


Figure 2. The code
-
behind model in ASP.NET 2.0

The partial class uses a new keyword (
Expands
in Visual Basic, or
Partial
in C#) to
indicate that the code in
the class should be merged with another class at runtime.
Similarly, the ASPX page uses a new directive called
compilewith
to indicate its
association with the code
-
behind file.

Comparing Code
-
behind Files

If you are familiar with traditional ASP.NET 1.
x
code
-
behind files, you know that
Visual Studio inserts auto
-
generated control declarations and initialization code. This
auto
-
generated code is a direct result of the bi
-
directional synchronization between
the code
-
behind file and the ASPX file. A typical
ASPX page with a label would have a
corresponding code
-
behind file consisting of many lines of auto
-
generated text.

Listing 1. A code
-
behind file in ASP.NET 1.
x

namespace WebApplication1 { public class WebForm1 : System.Web.UI.Page {
protected System.Web.
UI.WebControls.Label Label1;
private void
Page_Load(object sender, System.EventArgs e) { } #region Web Form Designer
generated code override protected void OnInit(EventArgs e) { InitializeComponent();
base.OnInit(e); } private void InitializeComponent() {
this.Load += new
System.EventHandler(this.Page_Load); } #endregion } }

The auto
-
generated code not only defines the label (bold line), it also declares a new
event (page load) and automatically wires the event to an auto
-
generated method
wrapper (
Page_Loa
d()
).

In comparison, the same ASP.NET page in ASP.NET 2.0 generates a code
-
behind file
that is much cleaner.

Listing 2. A code
-
behind file in ASP.NET 2.0

namespace ASP { public partial class MyPage : System.Web.UI.Page { } }

The developer can access
Label
1
automatically and add events as needed. For
example, a
Page_Load
event can be added to initialize the label.

Listing 3. Adding events in the new code
-
behind file

namespace ASP { public partial class Webform1_aspx : System.Web.UI.Page { void
Page_Load(obj
ect sender, EventArgs e) { Label1.Text = "Hello ASP.NET 2.0"; } } }

The event syntax can be generated through Visual Studio 2005. The resulting code
-
behind file is much shorter and free from any auto
-
generated code. The ASP.NET
runtime automatically wires
the events in the code
-
behind to the controls in the
ASPX. In other words, the ASP.NET runtime now automatically performs the code
generation that was performed by Visual Studio.

The benefit of the new two
-
step compilation is that it allows you to compile
the code
-
behind class into a binary and then support deploying the .aspx file as html source
for later modification. You could not deploy compiled code
-
behind and modify the
.aspx html source later, as the .aspx source was the partial type that the code
-
b
ehind was compiled with.

Inheritance Complexity

The new code
-
behind model greatly reduces the inheritance complexity. Because the
ASPX page does not directly inherit from the code
-
behind file, the code
-
behind file no
longer needs to define and support all
of the controls defined on the ASPX page.
Similarly, the code
-
behind file can automatically access any of the controls on the
ASPX page without requiring the declaration code that was required in ASP.NET 1.
x
.
All of this is possible because the ASP.NET run
time automatically inserts the required
declaration and event wiring code into the final compiled file. Because the runtime
takes on that responsibility, neither the code developer nor the Web developer needs
to worry about it.

During design time, the lin
kage is maintained by Visual Studio 2005. The Visual
Studio environment leverages the ASP.NET runtime compilation piece to ensure that
the code developer and Web developer can work in synchronization.

Compilation Complexity

Because the new code
-
behind file
is joined to the ASPX page and compiled into a
single complete class at runtime, the compilation complexity disappears. That is, the
code
-
behind file is automatically synchronized with the ASPX page. Even with the
new compilation model it is still possibl
e to have unsynchronized code, but the issue
can be quickly located because the resulting exception is much more explicit.

Compilation

Thanks to the page model introduced in ASP.NET 1.
x
, the compilation process for an
ASP.NET Web page has always been divid
ed into two phases. First, the code
-
behind
files and any other supporting classes are compiled into an assembly, and then the
individual ASPX files are compiled at runtime. Although this model has many
advantages, it has a few drawbacks. ASP.NET 2.0 offers
several alternatives to the
basic model, providing a wider range of compilation options depending on your
specific needs.

Compilation in ASP.NET 1.
x

The primary compilation model in ASP.NET 1.
x
resulted in one application assembly
(containing all of the c
ompiled code
-
behind files and other source code) and one
temporary assembly created for each ASPX page that was requested. In some cases,
compiler optimizations such as batching may cause the temporary ASPX pages to be
compiled into the same assembly. In e
ither case, each ASPX page is compiled into a
temporary assembly so that it can be loaded into the ASP.NET runtime.


Figure 3. Compilation in A
SP.NET 1.
x

Although this model has advantages, it also has two primary disadvantages. First,
the ASPX pages must be deployed to the Web site in human readable form. If your
developers used the
code
-
inline
model, that means that some or all of your business

logic may also be deployed on a production server. Although IIS and ASP.NET are
configured not to expose the raw ASPX pages, a clever attacker could still access the
files through any exploit that opened up access to the Web server. Second, the first
time
anyone requests a Web page, the response will be slower than normal, as the
ASP.NET runtime has to compile the ASPX page.

The only control a developer has over this process is whether or not to batch
-
compile
the ASPX pages. In ASP.NET 1.
x
, you can configu
re batch
-
compilation in the
web.config file by modifying the <
compilation
> tag.

Listing 4. Configuring batch
-
compilation

<compilation
batch
="true|false"
batchTimeout
="number of seconds"
maxBatchSize
="maximum number of pages per batched compilation"
maxBatc
hGeneratedFileSize
="maximum combined size (in KB) of the generated
source file per batched compilation" </compilation>

Batch
-
compilation makes a trade, of start
-
up time for reduced load time, on the first
request of a Web page. The other benefit of batch
-
c
ompilation is that all of the ASPX
files are compiled into a single temporary assembly rather than one temporary
assembly per page.

Compilation in ASP.NET 2.0

ASP.NET 2.0 offers three different compilation models for a Web application:



Normal (ASP.NET 1.
x
)

In a normal ASP.NET Web application, the code
-
behind files were compiled into an assembly and stored in the
/bin
directory.
The Web pages (ASPX) were compiled on demand. This model worked well for
most Web sites. However, the compilation process made th
e first request of any
ASP.NET page slower than subsequent requests. ASP.NET 2.0 continues to
support this model of compilation.



Deployment pre
-
compilation

A new feature of ASP.NET 2.0 allows for full
compilation of your project prior to deployment. In t
he full compilation, all of the
code
-
behind files, ASPX pages, HTML, graphics resources, and other back
-
end
code are compiled into one or more executable assemblies, depending on the
size of the application and the compilation settings. The assemblies cont
ain all
the compiled code for the Web site and the resource files and configuration files
are copied without modification. This compilation method provides for the
greatest performance and security at the cost of removing all ability to modify
the Web site
post
-
deployment. If you are working with highly visible or highly
secure Web sites, this option is the best choice for final deployment. However, if
you are building a small site running on your local intranet, and the site changes
frequently, full pre
-
co
mpilation may be over kill.



The ASP.NET 2.0 compilation model also allows you to precompile all the
code
-
behind files for your application and still make updates to your code. You
can compile your code
-
behind and original .ASPX files (both partial classes
) into a
single precompiled class (the page's base class). If you chose to edit your .aspx
file at runtime, you must simply recompile your page.



Full runtime compilation

At the other extreme of deployment
precompilation, ASP.NET 2.0 provides a new mechan
ism to compile the entire
application at runtime. That is, you can put your uncompiled code
-
behind files
and any other associated code in the new
\
app_code
directory and let ASP.NET
2.0 create and maintain references to the assembly that will be generated
from
these files at runtime. This option provides the greatest flexibility in terms of
changing Web site content at the cost of storing uncompiled code on the server.

Choosing the best compilation option will depend on your exact circumstances and
needs,
but the compilation model remains flexible. Even if you choose to make use
of the
\
app_code
directory to store your code
-
behind files, you may still deploy
your application using the full compilation method.

Batch
-
Compilation

In ASP.NET 2.0, you can batch
compile any application with a single URL request. As
with ASP.NET 1.x, batch compiling removes the delay on the first page request, but
creates a longer cycle time on startup. In addition, batch compilation still requires
that the code
-
behind files are c
ompiled pre
-
deployment.

The Web.config batch compilation settings still work in ASP.NET 2.0. The advantages
of batch compilation are that the pages are immediately available to the first user,
and that any errors in the ASPX pages will be detected during t
he batch compilation.
However, batch compilation does add a delay to the application start up and must be
built into the Web.config file. It should be noted that if a file fails, it is thrown out of
the batch.

Deployment Pre
-
Compilation

Deployment pre
-
comp
ilation allows you to create one or more assemblies that are an
executable version of your Web site. The resulting assemblies contain the compiled
code for the Web site. HTML pages, resources, configuration files, and ASPX pages
are copied separately.

Dep
loyment pre
-
compilation requires the use of a command line utility called
aspnet_compiler.exe. This utility creates a target deployment directory that contains
a
/bin
directory with assemblies, and stub files for the various ASPX pages. The
utility can als
o be used to do an in
-
place precompilation, similar to the behavior of
calling the "magic page." The stub files share the names of your ASPX pages, but
contain simple code that calls into the compiled assembly. In other words, the ASPX
pages are simply emp
ty shells rather than fully functional pages.

By pre
-
compiling the Web site for deployment, you gain increased security because
none of your code can be accessed without decompiling the assembly. For increased
protection, you can obfuscate the resulting a
ssembly and make your Web application
even more secure. The primary disadvantages of deployment pre
-
compilation are
that you have to perform these steps prior to deployment, and you can't change your
Web site after it has been deployed. If you want to make
changes, you have to
recompile the Web site and redeploy it.

For most major Web applications, the deployment pre
-
compilation option will be the
preferred mechanism for deployment, as it reduces the amount of raw code deployed
on the Web server and offers
the best security. The increased process can be built
into the normal development/test/deployment cycle without any significant lose of
productivity.

Full Runtime Compilation (the
\
app_code Directory)

In all three compilation methods described so far, you
have to compile all code files
(code
-
behind and supporting classes) prior to deployment. In ASP.NET 2.0, you have
the code directory.

The
\
app_code
directory is a special directory that holds uncompiled classes. At
runtime, the ASP.NET runtime compiles the
contents of this directory into an
assembly that is automatically referenced by the ASPX pages in the application. In
other words, by using the code directory, you can avoid creating and referencing
separate assemblies for your supporting code. The advant
age of the code directory is
that you can deploy without fully compiling your project, thereby reducing mismatch
potential. The drawback is that you are potentially exposing uncompiled code on
your server.

This option works best for ASP.NET applications t
hat do not require large amounts of
support code (either in the form of code
-
behind files or external objects). For a
simple application, the ability to rapidly deploy and test the system provides several
advantages over the more robust compilation methods
.

Page Lifecycle

ASP.NET 2.0 offers two major changes in the lifecycle of an ASP.NET page. First,
ASP.NET 2.0 exposes new events to support new features, including master pages,
personalization, and the integrated mobile device support. Second, ASP.NET 2.0

introduces cross
-
page posting for Web forms.

New Events

ASP.NET 2.0 provides a more granular page lifecycle method stack as compared to
ASP.NET 1.
x
. The added methods provide a greater level of control to the Web
developer. These events can be accessed th
rough the Page object on any ASP.NET
page.

Table 1 shows the comprehensive method list. The
Method
column displays the
actual event method name, and the
Active
column indicates whether the event is
always active or only active during
PostBack
actions. For
example, the new
TestDeviceFilter
method can be used to determine which device filter is in place,
and use this information to decide how to display the page. On the other hand, the
new
LoadControlState
method only fires during a postback. This method can
be
overridden (in conjunction with
SaveControlState
) to create alternate serialization
schemes for saving and restoring control state during a postback.

Table 1. Page Lifecycle methods

Method

Active

Constructor

Always

Construct

Always

TestDeviceFilter

A
lways

AddParsedSubObject

Always

DeterminePostBackMode

Always

OnPreInit

Always

LoadPersonalizationData

Always

InitializeThemes

Always

OnInit

Always

ApplyControlSkin

Always

ApplyPersonalization

Always

OnInitComplete

Always

LoadPageStateFromPersiste
nceMedium

PostBack

LoadControlState

PostBack

LoadViewState

PostBack

ProcessPostData1

PostBack

OnPreLoad

Always

OnLoad

Always

ProcessPostData2

PostBack

RaiseChangedEvents

PostBack

RaisePostBackEvent

PostBack

OnLoadComplete

Always

OnPreRender

Alway
s

OnPreRenderComplete

Always

SavePersonalizationData

Always

SaveControlState

Always

SaveViewState

Always

SavePageStateToPersistenceMedium

Always

Render

Always

OnUnload

Always

Looking at the low level details of the page lifecycle, we can see where
many of the
features that are available in ASP.NET 2.0, such as themes and personalization,
would naturally be implemented. For example, a theme would be processed in the
IntializeThemes
event, whereas personalization data would be loaded in the
LoadPerson
alizationData
and later applied in the
ApplyPersonalization
method.
Note that method order is extremely important with respect to which UI elements
will determine the final look and feel of your Web applications.

Cross Page Posting

The other major change i
n page lifecycle involves post back events and Web Forms.
In ASP.NET 1.
x
, Web Forms automatically postback to their host page. That is, when
a user submits a form, the form data is always submitted back to the page
containing the original form. This design
decision allows for easy storage of control
state, but limits the ability of the developer to perform more complex operations.

In ASP.NET 2.0, Web Form controls have a new property that lets the developer
decide where the form data should be sent on a su
bmit action. In most cases, the
postback mechanism will be desired, and it is therefore still the default. However, if
the developer wants to post data to a different form, it is now possible.


Figure 4. Postback and cross page posting

You can, for example, create a multi
-
page wizard consisting of several different
forms. Each form submits to the next page in the sequence, until the user reaches
a
summary page where final validation can occur. Data from the last page can be
accessed in the current context by means of the
PreviousPage
object. The
PreviousPage
object stores the validated data from the previous page for use in the
current page. Than
ks to this object, cross page posting doesn't sacrifice control
persistence. If your user needs to back up one form in the sequence, the page data
is immediately accessible and the user won't have to re
-
enter all of the data.

Extensibility

ASP.NET was orig
inally designed as an open framework. That is, many of the
modules and components that make up ASP.NET can be extended, modified or
replaced to suit your particular needs. In ASP.NET 2.0, the extensible nature of the
framework is clearly illustrated with t
he new
HTTPHandlers
and
HTTPModules
that
are now a standard part of the framework.

The Request Pipeline

In ASP.NET, requests are passed from the Web server through an Internet Server
Application Programming Interface (ISAPI) filter and on to the actual ASP
.NET
runtime.


Figure 5. The request pipeline

When IIS receives a request, the extension is mapped to an ISAPI filter according to
the IIS set
tings. The extensions .aspx, .asmx, .asd, and others are mapped to the
aspnet_isapi.dll, which is simply an ISAPI filter that launches the ASP.NET runtime.
Once a request hits the ASP.NET runtime, it starts at the
HTTPApplication
object,
which acts as the
host for the ASP.NET Web application. The
HTTPApplication

object:

1.

Reads the machine and application level configuration files.

2.

Passes the request through one or more
HTTPModule
instances. Each
HTTPModule
provides a service such as session maintenance,
au
thentication, or profile maintenance. These modules pass the request back
to the
HTTPApplication
.

3.

Passes the request to an
HTTPHandler
based on the verb and the path. The
verb refers to the HTTP verb used in the request (GET, POST, FTP, and so on)
and the
path refers to a URL within the application. Depending on how the
handlers are configured, the request may be processed as an ASP.NET page
(
System.Web.UI.Page
is an implementation of
IHTTPHandler
), or the
request may trigger another action such as the bat
ch
-
compilation of all Web
pages (precomiplation.asd triggers the
PrecompHandler
).

In ASP.NET 2.0, this model stays intact; however, several new modules and handlers
have been added to provide additional services. As with ASP.NET 1.
x
, you can
extend, repla
ce, or reconfigure any of the module or handler classes in order to
provide your own custom functionality.

New Modules

Naturally, new
HTTPModules
have been added to support the new services offered
in ASP.NET 2.0. Specifically, an ASP.NET application with
default module settings will
include new modules for:



SessionID

The session identification mechanism has been split off the
ASP.NET 1.
x
Session module in order to provide greater control over cookies,
URL rewriting, and other forms of session ID generatio
n.



Role Management

A new module has been added for providing role
-
based
services in support of the new user identification mechanisms. This module helps
link ASP.NET applications to the role
-
based security built into the .NET
framework.



Anonymous Identif
ication

The new personalization features support
anonymous users. This module helps keep track of which features an anonymous
user can access, and how these features are maintained between requests.



Profile

The profile module links to the new profile serv
ice and helps provide
user specific persistent data storage.

In addition to these new modules, the behaviors of some of the older modules have
changed: for example, the output caching module now supports the new caching
techniques described later in this
white paper.

New Handlers

In addition to the new modules, ASP.NET 2.0 introduces new handlers to support the
application configuration tools and other new features such as the batch
-
compilation
request. The most important of the new handlers include the ".
axd" family which
process Web site administration requests. These handlers launch the internal
administration tools that allow developers to configure ASP.NET users as well as
other settings. The administrative handlers include:



Web Administration

The
Web
AdminHandler
is the main page for the
administrative Web site. This handler provides the starting point for
administering ASP.NET 2.0 Web applications.



Trace

The ASP.NET 1.
x

TraceHandler
has been improved and is the only
"axd" handler that was available i
n ASP.NET 1.
x
.



Web Resources

Web resources can now be configured post
-
deployment
thanks to the new administrative tool and the
WebResourcesHandler
.



Cached Images

The
CachedImageServiceHandler
provides support for
caching graphical components.



Counters

T
he
SiteCountersHandler
works with the page counters module
to provide access statistics for an ASP.NET 2.0 application.



Precompile

As mentioned earlier, the
PrecompHandler
can be used to
batch
-
compile all of the ASPX pages in an ASP.NET application.



Web
Part Export

The
WebPartExportHandler
provides support for storing
and transferring Web Part layouts. Web Parts are a new mechanism for
personalizing the look and contents of a portal
-
style Web application.

As always, the
HTTPForbiddenHandler
is linked to
any file type that should never
be returned. In ASP.NET 2.0, the list of forbidden file types has been expanded to
include master pages, skin files, and other new developer components.

Advanced Caching Techniques

One way to improve the performance of any W
eb application is to cache static
content in memory. Cached content is always returned faster than freshly rendered
content. However, the tradeoff is that cached content may become stale. ASP.NET
1.
x
supports several kinds of caching, including:



Page leve
l

Each page may be cached as a whole piece or based on the
parameters used to access the page. The cached page expires after a fixed time.



Page fragment

If the page was built with user controls (.ascx files), then the
user controls could be cached indepen
dently of the rest of the page content.



Programmatic caching

The developer could also cache objects, thanks to the
cache API. The cache API offers the distinct advantage of providing a means to
create different types of dependencies for when the cache sho
uld be flushed.

In ASP.NET 2.0, the page level caching mechanism has been extended to support
database dependencies. With a database cache
-
dependency, a cached page can be
tied to a particular table in a SQL Server database. When the table changes, the
ca
che will automatically expire. In addition, a developer can now use post
-
cache
substitution to replace part of the cached content with refreshed content. Post
-
cache
substitution allows an application to use page level caching even if part of the page
shoul
d be dynamically generated.

Database Cache Invalidation

For most data
-
driven Web sites, caching can be a thorny topic, especially when a
situation demands the need for caching and the necessity of up
-
to
-
date data. In
ASP.NET 1.
x
, pages could be cached for
a length of time and organized by input
parameters (querystring or POST parameters):

Listing 5. ASP.NET 1.
x
output cache directive

<%@ outputcache duration="3600" varybyparam="ProdID" %>

For example, the code in Listing 5 caches a page in memory for one h
our based on
the variable
ProdID
. The problem that arises in the above example is what to do if
relevant business data is updated elsewhere. For example, consider a product
catalog page cached by product ID. If information about this product (quantity
avai
lable or price, for example) is updated from an administrative site, incorrect data
is cached and displayed to customers. With the previous version of ASP.NET, the
solution to this problem would require either manually removing the page from cache
using
Re
sponse.RemoveOutputCacheItem
, or waiting until the
duration
time
expires and allowing the system to update the page automatically.

ASP.NET 2.0 addresses this issue by providing support for database cache
dependencies. Table level notifications are availabl
e when working with SQL Server 7
and 2000, and Microsoft SQL Server 2005 will offer notifications on an even more
granular level. For example, the following code caches a product page for up to 1
hour, but adds a second dependency on a database table.

List
ing 6. ASP.NET 2.0 database cache example

<%@ outputcache duration="3600" varybyparam="ProdID"
sqldependency="MyDatabase:Products"
%>

Using the new
sqldependency
attribute, the cached page will expire if any changes
are made to the Products table. The
sql
dependency
attribute must reference a
datasource
that is configured in the web.config file. The
datasource
identifies the
database connection and necessary parameters to make the dependency notification
work.

Custom Cache Dependencies

ASP.NET 2.0 ships wi
th one
CacheDependency
implementation, the
SQLCacheDependency
class, which supports Microsoft SQL Server. Implementing a
new cache dependency would be an involved process, but is possible due to the
extensible nature of ASP.NET 2.0. In other words, you cou
ld create your own
CacheDependency
class to provide similar functionality for other database systems
such as Oracle or Sybase.

Post Cache Substitution

For those cases where a few page elements remain dynamic but the majority of a
page would benefit from ca
ching, ASP.NET 2.0 provides a feature known as post
cache substitution. Post cache substitution is used to inform the ASP.NET runtime
that a particular element, while present on a cached page, should be reevaluated
before the page is presented to the user.

There are two ways to use this feature:



Call the new
Response.writeSubstitution
method, passing a reference to
the substitution callback function.



Add an
<asp:substitution>
control to the Web page and set the
methodname
attribute to the name of the call
back function.



For either option an
@OutputCache
directive, specifying the duration and
location of the dependency, should be added to the page.

Implementing Post
-
Cache Substitution

Controls that are post
-
cache substitution
-
aware can be created to take a
dvantage of
this feature. An example of such a control is the
AdRotator
control. Listing 7
illustrates a page that:



Retrieves data from the authors table of the Pubs database.



Binds the data to a
GridView
control.



Displays ads from an
AdRotator.




Displa
ys the time the page was created in a label control.

An
<asp:substitution>
control (bold lines in the listing) has also been added to the
example. This control has its
methodname
attribute set to
uncachedUpdate
(a
method that returns string output

in this
case, the current time). The substitution
control will return the correct time, regardless of what has been cached.

Listing 7. PostCache.ASPX Source code

<%@ Page language="c#" Codefile="PostCache.ASPX.cs" AutoEventWireup="true"
Inherits="WebApplication1
.PostCache" %> <%@ outputcache duration="30"
varybyparam="none" %> <!DOCTYPE HTML PUBLIC "
-
//W3C//DTD HTML 4.0
Transitional//EN" > <HTML> <HEAD> <title>WebForm1</title> </HEAD> <body
MS_POSITIONING="GridLayout"> <form id="Form1" method="post"
runat="server
"> <DIV style="DISPLAY: inline; Z
-
INDEX: 101; LEFT: 32px; WIDTH:
160px; POSITION: absolute; TOP: 24px; HEIGHT: 8px" align="right"
ms_positioning="FlowLayout"> this page was created at: </DIV> <asp:Label
id="CreatedTime" style="Z
-
INDEX: 102; LEFT: 200px; PO
SITION: absolute; TOP:
24px" runat="server" Width="120px" Height="16px"> </asp:Label>
<asp:substitution id="UpdatedTime" methodname="uncachedUpdate" style="Z
-
INDEX: 103; LEFT: 200px; POSITION: absolute; TOP: 48px" runat="server"
Width="112px" Height="11px"
> </asp:substitution> <DIV style="DISPLAY: inline;
Z
-
INDEX: 104; LEFT: 32px; WIDTH: 160px; POSITION: absolute; TOP: 48px;
HEIGHT: 16px" align="right" ms_positioning="FlowLayout"> and last updated at:
</DIV> <asp:AdRotator id="Ads" style="Z
-
INDEX: 105; LEFT
: 312px; POSITION:
absolute; TOP: 16px" runat="server" Width="80px" Height="60px"
AdvertisementFile="img/Ads.xml"> </asp:AdRotator> </form> </body> </HTML>

The code
-
behind file for this page contains the event necessary to support the post
-
cache substitut
ion on the
uncachedUpdate
method. Note that the
Page_Load

method reports the time the page was loaded, so that we can determine when
caching is occurring.

Listing 8. PostCache.ASPX.cs

using System; using System.Collections; using System.ComponentModel; usi
ng
System.Data; using System.Drawing; using System.Web; using
System.Web.SessionState; using System.Web.UI; using
System.Web.UI.WebControls; using System.Web.UI.HtmlControls; namespace
WebApplication1 { public class PostCache : System.Web.UI.Page { protect
ed
System.Web.UI.WebControls.Label CreatedTime; protected
System.Web.UI.WebControls.Label UpdatedTime; protected
System.Web.UI.WebControls.AdRotator Ads; private void InitializeComponent() {
this.Load += new System.EventHandler(this.Page_Load); } private v
oid
Page_Load(object sender, System.EventArgs e) { CreatedTime.Text =
DateTime.Now.ToShortTimeString(); } protected String uncachedUpdate() { return
DateTime.Now.ToShortTimeString(); } } }

Post
-
Cache Substitution in Action

Figure 6 shows the output from
the
PostCache
page. The first time the application is
run, we can see that the "page created" and "last updated" times are the same.


Figure 6.
Output from PostCache.ASPX

On subsequent calls to the same page we can see the effect of post cache
substitution. Although the page
-
creation time and the image remain the same, the
last updated time changes.


Figure 7. PostCache output on second request

Both the creation time and
adRotator
image remain constant because of the
caching directive. The page is cached for 30 seconds. Once the time h
as passed,
both the creation time and the
adRotator
would update on the next request.
However, the
<asp:substitution>
control, which calls the
uncachedUpdate()

method, will update every time the page is requested regardless of its cached status.

With prope
r manipulation of post cache substitution, developers can dramatically
increase the performance of their Web applications by updating only the dynamic
aspects of their pages. Coupled with database cache invalidation and asynchronous
page updates, Web appli
cations that are developed with ASP.NET 2.0 will remove
many of the limitations imposed by the Web's traditional request and response
architecture.

Performance

With the infrastructure changes and additional features in ASP.NET 2.0, one question
that remain
s is, how fast does ASP.NET 2.0 perform? Although performance metrics
are not available as ASP.NET 2.0 is still in development, significant effort was made
to ensure that performance remained consistent or improved throughout all aspects
of the ASP.NET 2.0
framework.

Improved Request Pipeline

One area in which every developer will see improved performance is in the request
pipeline. Despite the addition of many new event hooks, the basic ASP.NET request
stack is faster than in ASP.NET 1.1. You can evaluate
the improved performance by
creating a simple page that displays "Hello World." Because the page has no
advanced functionality, you are directly testing the
HTTPHandler
and
HTTPModule

pipeline, as well as the ISAPI plug
-
in that connects ASP.NET 2.0 to IIS.
Regardless of
which version of IIS you are using, you should see increased performance as this
code has been optimized for faster throughput.

Memory Management Improved with IIS 6.0

Some of the performance improvements in ASP.NET 2.0 only come in conjunct
ion
with IIS 6.0. For example, on IIS 6.0, the working set for the worker process was
reduced by approximately 50 percent in load tests using 100 concurrent users
requesting a page with several controls. That means that, for a given server, the
operating s
ystem is using about half the resources that were necessary before.

In a test designed to mimic a moderately complex ASP.NET page, the system load
(memory and CPU usage) dropped dramatically when compared to the same page
running on IIS 5.0. This particul
ar performance enhancement was accomplished by
moving the response buffers from managed memory to native memory. By removing
the necessity to pin managed memory to a particular response, ASP.NET 2.0
eliminates a resource bottleneck and generates faster res
ponses for each request.

Other performance improvements take advantage of close integration of the IIS 6.0
with the Windows Operating System kernel. IIS 6.0 performs some of its caching and
buffering at the kernel level, which provides increased performan
ce for all Web
applications, including ASP.NET.

Other Improvements

As a developer, you should expect ASP.NET 2.0 to perform as fast as, or faster than,
ASP.NET 1.
x
. Now that the core functionality has been built, additional performance
improvements should
be expected in the final release of ASP.NET 2.0.

Conclusion

ASP.NET 2.0 contains many architectural enhancements designed to improve
developer productivity. Not only has the code model been improved to reduce
conflicts, the compilation process has been exp
anded to provide a wider variety of
options for compiling and deploying Web applications. The extensibility of the
ASP.NET framework has once again been shown through the new
HTTPModules
and
HTTPHandlers
, which support many of the new features found in ASP
.NET,
including personalization, master pages, and the administrative site. Caching has
been improved to allow for database dependencies and post cache substitution.
Internally, ASP.NET 2.0 contains drastic improvements over its predecessor; the new
implem
entation incorporates a number of developer
-
driven improvements while
adhering to industry best practices. ASP.NET 2.0 provides a world class Web
development platform that is built to handle the complexity of enterprise Web
application development.