Cutting Edge

AJAX Application Architecture, Part 1

Dino Esposito

Code download available at:CuttingEdge2007_09.exe(333 KB)


AJAX to the Rescue
The AJAX Architecture
What's an AJAX Framework?
ASP.NET AJAX Extensions
A Look at Partial Rendering
Anatomy of an AJAX Postback
Optimization Techniques for Partial Rendering
Weighing Partial Rendering

Whether you're a system administrator, a designer, or a developer, your job will be significantly affected by AJAX. Administrators have to ensure that the security bar is still high enough to face new types of possible attacks. Intranet administrators have to guarantee that JavaScript is not disabled on any browsers. Web designers have new challenges to pursue due to features attainable with AJAX that were once impossible or impractical. And developers have a new API and a new overall approach to programming to become familiar with. All that said, what does AJAX mean for architects?

AJAX applications are challenging because they introduce brand-new concepts and a new foundation. The role of the architect is essential because the AJAX paradigm straddles both the client and the server environments. A clear architectural vision is critical for determining what logic and processing happens on the client and what remains on the server, as well as what data objects the client and the server are able to exchange.

AJAX to the Rescue

The Web was originally used to share static pages of information. Over just a few years, it evolved into a far more dynamic medium. Today, the Web is made up of extremely interactive pages; however, it still relies heavily on a paradigm that is based on full-page transitions. The more the user interacts with a page, the more frequently pages must be created and served back to the user's browser. There are many negative consequences that result from serving interactive pages in this manner, such as slow page refreshes and flickering. It's an inelegant solution that frequently leads to a poor user experience. AJAX brings about a much-desired shift in this paradigm that allows for cleaner Web applications and it lays the groundwork for a new generation of applications. AJAX is really about the end user. With AJAX features, a Web application is much more interactive, more responsive. It's faster and friendlier. The user is encouraged to do more with the page as interaction and responses (and feedback in case of slow operations) are all handled more elegantly. Overall, the user has a much better experience.

With AJAX, more code is executed on the browser and this requires more script being given to the client pages. But this leaves some big questions to be answered. What kind of script? Who will write this script? And what architectural principles and patterns will this script adhere to?

In this column, I'll explain AJAX from an architectural standpoint and help you, the developers and architects, make thoughtful choices. At the same time, I'll give designers and administrators enough context information to help make their jobs easier. This is a pretty big topic, so I'm dividing it into two parts. Don't miss next month's column when I'll continue this discussion.

The AJAX Architecture

If you're considering AJAX, take a look at Figure 1, which illustrates the architectural implications of such a move. A traditional Web application does everything on the server. Only occasionally does the application emit script code to run a task on the client—for example, to handle data validation.

Figure 1 Classic Web Paradigm versus AJAX Paradigm

Figure 1** Classic Web Paradigm versus AJAX Paradigm **(Click the image for a larger view)

An AJAX application uses a client-side framework that takes care of issuing calls to the Web server. An AJAX server-side framework then takes care of the request and returns a data feed to the client. This will often be a JavaScript Object Notation (JSON) data stream, but other formats—such as XML, RSS, and CSV—can be used.

The client receives data feeds and updates the UI using JavaScript. The server responds to requests by returning raw data, encoded in a given format. Bandwidth consumption is minimized, the speed of the app increases since requests take less time to complete, and UI updates are able to take effect with no visible postback. But while this solves many problems, the increase in action on the client also brings about new issues, such as new coding practices, new security hazards, accessibility concerns, and so on.

What's an AJAX Framework?

To keep AJAX alive in a Web page, a few conditions must be met. First, you need JavaScript support from the browser. A full-time Internet connection is also required—an AJAX application can't work offline. When all the requests are made at the page level, as they are with non-AJAX applications, the browser can offer to navigate through a cached set of these pages, and thus can proceed offline. This same behavior would have to be coded explicitly in the script-based framework that partners with the browser in an AJAX application. There's a lot going on in this area and some new tools to help are being developed. The ability to take AJAX applications offline is a challenge for many software vendors.

A special framework is required by any serious AJAX application. Usually the framework of choice is articulated in separate client and server parts.

There are two main types of script code in an AJAX page: system-level code from the framework of choice and user-level code that implements the page's expected behavior. The system-level code provides the engine used to send asynchronous requests to the Web server and process any responses. The user-level code updates the UI of the page, essentially using Document Object Model (DOM) scripting. So here's one of those questions I mentioned earlier: Who writes which? To discuss this, I'll focus on a particular AJAX framework—ASP.NET AJAX Extensions.

ASP.NET AJAX Extensions

An extension to ASP.NET 2.0, ASP.NET AJAX Extensions provides AJAX capabilities to new and existing Web sites. There are two programming models for ASP.NET AJAX: partial rendering and remote services. They assume two radically different architectures in the application and consequently have different pros and cons. (You've probably already figured out that most features in AJAX involve trade-offs.)

In brief, partial rendering allows you to maintain an architecture similar to a classic ASP.NET 2.0 application. It just provides you with a set of new server-side tools you can use to implement flicker-free page updates.

Remote services, on the other hand, involve a service-oriented back end invoked by a relatively script-heavy AJAX front end. Nearly all fundamental application processes—including authentication, data paging, and sorting—must be redesigned. Server-side code must be factored out to application-specific services and a format (such as JSON) must be selected for data exchange. Finally, a front end must be arranged, paying due attention to limit your coding to UI-level tasks and keeping most business logic off the client.

The remote services approach provides a more complete AJAX experience, while partial rendering offers a smoother transition with a progressive enhancement of the features already in your existing application.

The two approaches can be mixed to some extent. You can, for instance, keep the same traditional Web architecture, add some flicker-free updates here and there, and then take time to refactor some key features in a service-oriented manner. ASP.NET AJAX Extensions provides several key ingredients, but significant pieces of the work for creating great AJAX applications is still up to you. Figure 2 shows the client and server components of the ASP.NET AJAX Extensions framework.

Figure 2 Components of the ASP.NET AJAX Extensions Framework

File Location Description
MicrosoftAjax.js Client Contains functions to extend JavaScript with object-oriented constructs. It extends the prototype of built-in JavaScript objects and defines new helper classes, such as StringBuilder.
MicrosoftAjaxWebForms.js Client Contains the JavaScript classes that form the network stack and all classes that implement the client-side partial rendering engine.
MicrosoftAjaxTimer.js Client Represents the client-side object model for the new AJAX System.Web.UI.Timer server control. This is basically a server wrapper for a browser's timer object.
System.Web.UI.ScriptManager System.Web.Extensions Orchestrates the download of proper JavaScript files and client-side data, including the AJAX library, proxy classes for remote services, localized version of script files, and globalization data.
System.Web.UI.UpdatePanel System.Web.Extensions Defines a region of a page that can be refreshed through an AJAX postback in a flicker-free way.
System.Web.UI.UpdateProgress System.Web.Extensions Defines a server-side template that can be used to provide feedback to the user while a long partial rendering operation is taking place.
System.Web.UI.Timer System.Web.Extensions Helper server control that posts back the AJAX way when a child client timer times out.

A Look at Partial Rendering

Jeff Prosise's June 2007 Wicked Code column (msdn.microsoft.com/msdnmag/issues/07/06/WickedCode) offers an excellent discussion about partial rendering with ASP.NET AJAX. From an architectural viewpoint, partial rendering doesn't add anything new. It's just a cool way of enhancing legacy applications with some AJAX capabilities—the most important of which is flicker-free page updates.

Partial rendering doesn't require learning a lot of new skills, and it has a very limited impact on existing code. It also offers a straightforward fallback mechanism for aspects of an application that may suffer from the adoption of AJAX—security and accessibility, for example. Basically, if in the upgrade process you get into trouble when turning certain parts of existing code into AJAX, you can just leave those code blocks as they were and move on.

A partial rendering request is often referred to as an AJAX postback. The term is quite appropriate, perfectly representing what really happens. An AJAX postback is like a classic ASP.NET postback, except that it is carried out by a piece of script code defined in the client-side ASP.NET AJAX library. Although dressed like a pure AJAX remote call, an AJAX postback looks like a regular postback request to the ASP.NET runtime components. Once on the server, the request goes through the typical lifecycle of postback requests and raises such events as Init, Load, and PreRender. On the server, an AJAX postback differs from a classic ASP.NET postback only in the algorithm it uses to render the final markup. The different algorithm is key to the improved performance and absence of page flickering. However, the application model remains the same as in ASP.NET. Figure 3 shows the modified lifecycle of an AJAX postback request.

Figure 3 Lifecycle of an AJAX Postback

Figure 3** Lifecycle of an AJAX Postback **

Everything is the same in the AJAX and ASP.NET postbacks, except the implementation of the rendering stage. An AJAX postback still fires notification events, such as Load and PreRender, and it still processes viewstate information and raises state changed and postback events, such as TextChanged and Click.

An ASP.NET AJAX page must include one instance of the ScriptManager control. This control is the real nerve center of ASP.NET AJAX pages. It takes care of linking the page to any required framework script files and orchestrates partial rendering if it detects that an AJAX postback is occurring. The ScriptManager control checks an HTTP header in the request to determine whether the request is an AJAX postback. The following is an excerpt from the MicrosoftAjaxWebForms.js file that sets the HTTP header before triggering the AJAX request:

request.get_headers()['X-MicrosoftAjax'] = 'Delta=true';

To see what makes the rendering stage different for an AJAX postback, take a close look at the following excerpt from the System.Web.Extensions assembly:

protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); if (IsInAsyncPostBack) PageRequestManager.OnPreRender(); }

In particular, the code snippet shown above comes from the ScriptManager control. As you can see, the script manager registers a pre-rendering event handler. When fired, the handler detects whether it is engaged in an AJAX postback and, if so, invokes a method from the PageRequestManager internal class. The OnPreRender method on the PageRequestManager class does the following:

internal void OnPreRender() { _owner.SetRenderMethodDelegate( new RenderMethod(this.RenderPageCallback)); }

Quite simply, the method sets a specific subroutine to render the markup for the current request. SetRenderMethodDelegate is a method defined on the System.Web.UI.Control class. Not intended for public use, this method basically assigns an event handler that the page or the control will use to render its contents. In the preceding code snippet, the method is invoked on the current page and ends up overriding the whole rendering process for the current request. The actual code responsible for the markup of an AJAX postback is therefore defined in the RenderPageCallback method—an internal method in the PageRequestManager class. (For more information on the ScriptManager control, see the article by Ben Rush in this issue of MSDN® Magazine.)

Basically the modified rendering process for an AJAX postback loops through all updatable panels in the page that are involved with the postback and accumulates the markup of each. All markup chunks, along with hidden fields and any error information, are packed into a response stream and passed to the client. Now let's dissect a typical partial rendering call in the context of a sample page.

Anatomy of an AJAX Postback

To make an ASP.NET page a partially rendered page, you must first add a script manager to the page and then define independently updatable regions by wrapping them with an UpdatePanel control. Here's an example:

<asp:ScriptManager runat="server" /> <asp:UpdatePanel runat="server" ID="UpdatePanel1"> <ContentTemplate> <%-- Markup of the region goes here --%> </ContentTemplate> </asp:UpdatePanel>

The UpdatePanel control doesn't alter in any way the visible markup generated for the region. It simply adds a surrounding <div> tag to the original markup:

<div id="UpdatePanel1"> <%-- Markup of the region goes here --%> </div>

What triggers an AJAX postback? How is it managed? And by whom? Whenever the script manager detects one or more UpdatePanel controls in the page, it emits the block of script as in the following:

<script type="text/javascript"> Sys.WebForms.PageRequestManager._initialize('ScriptManager1', document.getElementById('form1')); Sys.WebForms.PageRequestManager.getInstance()._updateControls( ['tUpdatePanel1','tUpdatePanel2'], [], [], 90); </script>

The _initialize method is a static method on the client-side PageRequestManager object (see MicrosoftAjaxWebForms.js). It creates a global instance of the PageRequestManager class and initializes it. The class acts as a singleton and the only available instance can be retrieved later through the getInstance method. The second statement of the preceding snippet registers an array of UpdatePanel controls with the client framework. Each server-side UpdatePanel control is referenced through its ID.

The key action happening here is inside the _initialize method. As I said, after creating the singleton instance of the class, the code initializes it. At this time, among other things, a handler is registered for the submit event of the DOM form object. This means that whenever the page submits a form, the AJAX script kicks in and places the request using XMLHttpRequest instead of letting the request go through a normal browser postback. The original set of form fields is maintained and some extra information is appended for the convenience of the server-side script manager. Hence, an AJAX postback uploads a bit more information than a regular ASP.NET postback.

The viewstate, as well as any other hidden fields, are carried out and uploaded to the server with the request. On the way back, an updated viewstate is downloaded along with new hidden fields, if any, and a likely shorter markup. In particular, the response includes only the markup for the updatable regions that have been modified during the postback. The list includes the UpdatePanel control that triggered the postback (and any nested panels), any other UpdatePanel controls in the page that have the UpdateMode property set to Always, and any UpdatePanel control that is programmatically refreshed. The following code is an example of how to programmatically refresh a panel based on run-time conditions:


Consider the sample page shown in Figure 4 and the response returned. You can use a variety of tools to monitor inbound and outbound HTTP packets. For this column, I used Nikhil Kothari's Web Development Helper tool.

Figure 4 Sample Page

<%@ Page Language="VB" CodeFile="Test.aspx.vb" Inherits="Test" %> <html xmlns="https://www.w3.org/1999/xhtml" > <head runat="server"> <title>Test :: Partial Rendering</title> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager runat="server" ID="ScriptManager1" /> <asp:UpdatePanel runat="server" ID="UpdatePanel1"> <ContentTemplate> <asp:TextBox runat="server" ID="TextBox1" /> <asp:Button runat="server" ID="Button1" Text="Update" /> <hr /> <asp:Label runat="server" ID="Label1" /> </ContentTemplate> </asp:UpdatePanel> </div> </form> </body> </html>

The response of an AJAX postback is a text stream that can be seen as a table of records with Size, Type, ID, and Content columns. Each record is referred to as a delta node. Figure 5 shows the table you obtain for my sample page.

Figure 5 Delta Node Table for the Sample Page

Size Type ID Content
249 updatePanel UpdatePanel1 <input name="TextBox1" type="text" value="Test" id="TextBox1" /> <input type="submit" name="Button1" value="Update" id="Button1" /> <hr /> <span id="Label1"></span>
52 hiddenField __VIEWSTATE  
56 hiddenField __EVENTVALIDATION  
0 asyncPostBackControlIDs    
0 postBackControlIDs    
13 updatePanelIDs   tUpdatePanel1
0 childUpdatePanelIDs    
12 panelsToRefreshIDs UpdatePanel1  
2 asyncPostBackTimeout 90  
9 formAction   Test.aspx
25 pageTitle   Test :: Partial Rendering

A delta node identifies a possible change that occurred during the AJAX postback. Not all responses feature the same set of delta nodes; it depends on what happens during the server lifecycle of the request and the structure of the original markup.

Figure 6 lists all currently supported delta nodes. The JavaScript code that is responsible for processing the delta table can be found in the MicrosoftAjaxWebForms.js file.

Optimization Techniques for Partial Rendering

After examining Figure 6, you'll note that the response is made up of two big blocks: markup and viewstate. Event validation data (a security-related feature of ASP.NET 2.0), custom hidden fields, scripts, and any other types of nodes usually take just a few dozen bytes all together. The size of the viewstate is an old problem for ASP.NET pages. Partial rendering with ASP.NET AJAX, unfortunately, does nothing to correct the problem. You still need to keep your viewstate lean and mean to improve download time. So what can you do to reduce the markup for a page? Essentially, you can have smaller panels that bring back just the minimum amount of markup you need for that particular click.

Figure 6 Partial Rendering Delta Node Type

Delta Node Type Description
updatePanel Stores the updated markup for a partial rendering region.
hiddenField Stores the content of a hidden field.
arrayDeclaration Stores an array declaration added to the response using the appropriate RegisterXXX method on the script manager.
scriptBlock Stores a script block added to the response using the appropriate RegisterXXX method on the script manager. The specified script is executed or inserted in the page based on which RegisterXXX method you used.
expando Stores an expando property added to the response using the appropriate RegisterXXX method on the script manager. The specified value is assigned to the specified property ID when the response is processed.
onSubmit Stores an onsubmit script block added to the response using the appropriate RegisterXXX method on the script manager.
asyncPostBackControlIDs Stores the ID of controls registered as asynchronous triggers for the update panels in the call.
postBackControlIDs Stores the ID of controls registered as postback triggers for the update panels in the call.
updatePanelIDs Stores the ID of the update panels involved with the call.
asyncPostBackTimeout Stores the timeout of the request in seconds.
childUpdatePanelIDs Stores the ID of any nested update panel refreshed in the call.
panelsToRefreshIDs Stores the ID of any update panels refreshed during the call, including panels refreshed programmatically.
formAction Stores the URL of the action form.
dataItem Stores any extra information generated on the server to be consumed by client components.
dataItemJson Stores any extra JSON serialized information generated on the server to be consumed by client components.
scriptDispose Stores a dispose script added to the response using the RegisterDispose method on the script manager. The specified script is executed on the client for the specified DOM element.
pageRedirect Stores the new URL to reach in case of a redirection.
error Stores error information in case an exception is raised during the postback.
pageTitle Stores the new title of the page.
focus Stores the ID of the new control holding the input focus.

Look again at the code in Figure 4. The logic in the page is fairly simple, but it illustrates the point. Basically, when the user clicks the button, any content in the TextBox is used to update the label.

The page contains only one UpdatePanel control that wraps everything: textbox, button, separator, and label. Logically speaking, this may be acceptable. If you have to identify a region in the page to refresh autonomously, this is a valid option. Defined in this way, though, the region contains a significant portion of code that isn't updated across postbacks. The TextBox and Button controls, for instance, are not updated in this page and the <hr> separator is plain static text.

A better option would be to reduce the UpdatePanel to comprehend the sole Label control—the unique server control that gets updated in any postback triggered by the button. In general, you should carefully identify postback relationships between controls—basically examining which updates which—and design updatable panels to include the minimum number of controls for a given user action. In the context of the sample shown in Figure 4, here's a better schema:

<asp:TextBox runat="server" ID="TextBox1" /> <asp:Button runat="server" ID="Button1" Text="Update" OnClick="Button1_Click" /> <hr /> <asp:UpdatePanel runat="server" ID="UpdatePanel1"> <ContentTemplate> <asp:Label runat="server" ID="Label1" /> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="Button1" /> </Triggers> </asp:UpdatePanel>

The UpdatePanel control now contains only the Label control. This means that no (unchanged) markup will be returned for the textbox and button controls. By default, an UpdatePanel control is refreshed when either one of its child controls causes a postback or another UpdatePanel in the page is refreshed. This behavior can be altered with some public properties—namely UpdateMode, ChildrenAsTriggers, and Triggers.

In particular, UpdateMode determines whether the UpdatePanel is set to refresh unconditionally (the default) or only under certain conditions. If you want a conditional refresh—a key setting for optimizing updatable panels—start by setting UpdateMode to Conditional:

<asp:UpdatePanel runat="server" ID="UpdatePanel1" UpdateMode="Conditional">

Note, though, that conditional updates are relevant only if you have multiple panels in a page.

There might be situations where you find it difficult to split a page into a set of normalized panels. A technique that might help you in these cases is preventing children from triggering postbacks. The ChildrenAsTriggers property is a Boolean property (true by default) that determines whether child controls of a panel act as triggers of AJAX postback events. In the following snippet, the Button1 control doesn't cause a refresh of the panel:

<asp:UpdatePanel runat="server" ID="UpdatePanel1" ChildrenAsTriggers="false"> <ContentTemplate> <asp:Button runat="server" ID="Button1" Text="Update" OnClick="Button1_Click" /> <asp:Label runat="server" ID="Label1" /> </ContentTemplate> </asp:UpdatePanel>

When a child button is clicked in a panel configured like this, an AJAX postback still occurs to execute any postback code attached to the button—for instance, the Button1_Click method—but no markup is returned to refresh the panel.

The third property involved with conditional refreshing is Triggers. This is a collection property and lists control events that will command a refresh of the panel, like so:

<asp:UpdatePanel runat="server" ID="UpdatePanel1"> <ContentTemplate> <asp:Label runat="server" ID="Label1" /> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" /> </Triggers> </asp:UpdatePanel>

In this case, the Click event on Button1 will refresh the panel. The Button1 control may be placed anywhere in the page. Note that I'm talking about server events. In other words, if you want to refresh a panel when the user changes the selection on a dropdown list, you must first add the AutoPostBack attribute to the dropdown list.

You can still configure a panel to refresh when a state-changed event occurs on the server during an AJAX postback. Consider the following code:

<asp:TextBox runat="server" ID="TextBox1" /> <asp:UpdatePanel runat="server" ID="UpdatePanel1"> <ContentTemplate> <asp:Label runat="server" ID="Label1" /> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="TextBox1" EventName="TextChanged" /> </Triggers> </asp:UpdatePanel>

The label is refreshed whenever the content of TextBox1 changes:

Sub TextBox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles TextBox1.TextChanged Label1.Text = TextBox1.Text End Sub

The TextChanged event, as well as other state-changed events, are server-side events that fire as a consequence of a postback. The page still needs a button, or an auto-postback control, to trigger the postback in order to update the label.

The chart in Figure 7 summarizes the potential benefits of applying optimization techniques to updatable panels. With partial rendering, the size of the request packet increases a bit, but even in the least optimized case the response you get back is smaller than in a classic ASP.NET scenario. And, of course, users won't experience flickering.

Figure 7 Benefits of Optimizing Updatable Panels

Figure 7** Benefits of Optimizing Updatable Panels **(Click the image for a larger view)

I should warn you, though, that pages with a huge viewstate may not benefit much from partial rendering. You might save 5KB of markup, but that's faint relief if you have to carry 30KB of viewstate.

But sometimes, viewstate is only an innocent scapegoat for an issue that originated elsewhere. Imagine you have a calendar control in an ASP.NET page and you use updatable panels to keep the refresh smooth:

<asp:UpdatePanel runat="server" ID="UpdatePanel1"> <ContentTemplate> <asp:Calendar runat="server" ID="Calendar1" /> </ContentTemplate> </asp:UpdatePanel>

The markup for this fragment is no less than 7KB and can grow up to 10KB if you add some styles. Now, if you disable the viewstate on the calendar, you save approximately 1KB of data, which is only about 10 percent of the total size. This is because the Calendar is a heavy control in terms of markup. The viewstate has little to do with it. An ASP.NET AJAX page shouldn't use a Calendar control for date-picking functions. Instead, the AJAX Control Toolkit provides an extender—the CalendarExtender control—that, when added to a plain TextBox, lets you pick dates, effectively saving 10KB of markup.

This code pops up a calendar whenever the textbox gets the input focus:

<asp:textbox runat="server" ID="TextBox1" /> <act:CalendarExtender ID="CalendarExtender1" runat="server" TargetControlID="TextBox1" OnClientDateSelectionChanged="updateLabel" Format="dd/MM/yyyy" /> <asp:UpdatePanel runat="server" ID="UpdatePanel1" UpdateMode="Conditional"> <ContentTemplate> <asp:label runat="server" ID="Label1" /> </ContentTemplate> </asp:UpdatePanel>

The calendar is created entirely on the client and only requires a couple of small icons to be downloaded. The extender automatically writes the selected date to the companion TextBox. However, with a bit of JavaScript code, you can handle the client date selection event and do whatever you need.

Weighing Partial Rendering

Partial rendering is the quickest way of spicing up an ASP.NET Web site with AJAX capabilities. It requires neither new skills nor a new architecture. Instead, it lends itself to progressively enhancing an existing Web site. But compared to a pure AJAX approach—direct client calls to remote services—partial rendering suffers from significant performance penalties.

As a rule of thumb, I recommend partial rendering as the best approach for building a rock-solid first AJAX version of a site. You can then progressively move away from the classic ASP.NET architecture and start building a set of back-end services and a thick presentation layer. In the next installment of Cutting Edge, I'll dive into the remote services approach to AJAX. It's neat, architecturally speaking, but it may require a complete redesign of your application and it raises a few new issues.

Send your questions and comments for Dino to cutting@microsoft.com.

Dino Esposito is a mentor at Solid Quality Learning and the author of Programming Microsoft ASP.NET 2.0 (Microsoft Press, 2005). Based in Italy, Dino is a frequent speaker at industry events worldwide. Get in touch with Dino at cutting@microsoft.com or join the blog at weblogs.asp.net/despos.