Click to Rate and Give Feedback
Related Articles
Here the author introduces SQL Server Data Services, which exposes its functionality over standard Web service interfaces.

By David Robinson (July 2008)
Here the author answers questions regarding the Entity Framework and provides an understanding of how and why it was developed.

By Elisa Flasko (July 2008)
Here we present techniques for programmatic and declarative data binding and display with Windows Presentation Foundation.

By Josh Smith (July 2008)
Systems that handle failure without losing data are elusive. Learn how to achieve systems that are both scalable and robust.

By Udi Dahan (July 2008)
More ...
Articles by this Author
In this installment, the author provides an enhanced implementation of the BST pattern and compares it to HTM solutions.

By Dino Esposito (July 2008)
AJAX is meant to go beyond mere partial page rendering. Find out where Dino Esposito thinks dynamic pages are headed in the future with ASP.NET AJAX.

By Dino Esposito (June 2008)
This month we begin a look at the Single Page Interface (SPI) model and some design patterns for designing AJAX applications.

By Dino Esposito (May 2008)
This month, use nested ListView controls to create hierarchical views of data and extend the eventing model of the ListView by deriving a custom ListView class.

By Dino Esposito (April 2008)
This month Dino Esposito shows you how to get Windows-style modal dialog boxes for your Web applications thanks to the Ajax Control Toolkit and some clever coding.

By Dino Esposito (Launch 2008)
This month Dino looks at AJAX control extenders again, adding more advanced features including masked editing and autocompletion.

By Dino Esposito (February 2008)
AJAX Extenders extend the behavior and features of ordinary Web controls so you can reduce postbacks and control input even better than with AJAX alone.

By Dino Esposito (January 2008)
Dino Esposito introduces the Microsoft AJAX Library and the JavaScript library for ASP.NET AJAX 1.0.

By Dino Esposito (December 2007)
More ...
Popular Articles
Kenny Kerr sings the praises of the new Visual C++ 2008 Feature Pack, which brings modern conveniences to Visual C++.

By Kenny Kerr (May 2008)
We will introduce you to the Visual Studio Profiler by walking through a sample performance investigation, pinpointing code inefficiencies in some sample applications.

By Hari Pulapaka and Boris Vidolov (March 2008)
Here we present a rundown of the various language paradigms of CLR-based languages via short language introductions and code samples.

By Joel Pobar (May 2008)
Here the author uses Document Information Panels in the Microsoft 2007 Office system to manipulate metadata from Office docs for better discovery and management.

By Ashish Ghoda (April 2008)
More ...
Read the Blog
The most fundamental form of Web testing is HTTP request/response testing. This involves programmatically sending an HTTP request to the Web application, fetching the HTTP response, and examining the response for an expected value. In the May 2008 issue of MSDN Magazine, Read more!
In the November issue of MSDN Magazine, Jeffrey Richter demonstrates some recent additions to the C# programming language that make working with the APM significantly easier. In the June ...
Read more!
The July 2008 issue of MSDN Magazine is now available online. Here's what's in the issue: Data Services: Develop ...
Read more!
The June 2008 issue features the first installment of a new MSDN Magazine column on software design fundamentals. We’ll discuss design patterns and principles in a manner that isn't bound to a specific tool or lifecycle methodology. In this issue, Jeremy Miller starts the Patterns in Practice column ...
Read more!
In the April 2008 issue of MSDN Magazine, Kenny Kerr introduced the Windows Imaging Component (WIC), showing you how you can use it to encode and decode different image ...
Read more!
A combination of the retained-mode graphics system and notification mechanisms such as dependency properties unleash the flexibility and power of Windows Presentation Foundation (WPF, allowing these objects to be targets of data bindings and animations. In the June 2008 issue of MSDN Magazine, Charles ...
Read more!
More ...
Cutting Edge
Custom Script Callbacks in ASP.NET
Dino Esposito

Code download available at: CuttingEdge0501.exe (161 KB)
Browse the Code Online
ASP.NET client callbacks represent a neat and elegant way to execute server-side code without posting and refreshing the current page. I discussed ASP.NET callbacks in the August and December 2004 installments of Cutting Edge, considering them from the perspective of rendered pages making background callbacks to the server, sending input data to the relevant page, and receiving a response. The response string can then be processed by the client however it sees fit, often manipulating the rendered page content through the Dynamic HTML (DHTML) object model and a callback JavaScript function embedded in the page.
While that use of callbacks is exciting, they can do more. A script callback mechanism can also add advanced functionalities to a server control. By implementing a couple of interfaces, any custom control can be endowed with script callback capabilities to use background round-trips to collect server data and update the user interface—the topic I'll cover this month.

Inspired by GridView Controls
If you've read my recent ASP.NET 2.0 GridView feature article, you know that the GridView control does not require you to refresh the whole page in order to display a new page of records. In fact, the GridView control provides an advanced engine for paging and sorting that is based on ASP.NET script callbacks. The data for the new page downloads behind the scenes, invisible to the user. Once it reaches the client, the data is collected by a JavaScript function and used to update the current view.
Paging and sorting callbacks are not 100 percent client-side solutions (if you need a purely client-side implementation, see the one Jeff Prosise built in the Wicked Code column in February 2004). The GridView's page and sort callbacks work on demand, downloading only the data needed; the whole data source is not downloaded onto the client. You still pay the price of a round-trip, but you're guaranteed the most current data even if that data has recently been updated on the server.
Having discovered that ASP.NET controls can support script callback capabilities had me all a-tingle for a while, and made me rush to figure out how to build my own.
Incidentally, the GridView is not the sole ASP.NET 2.0 control to sport a similar capability. Other view controls, such as TreeView, DetailsView, and FormView, provide the same feature out of the box. As a developer using a callback-enabled control, you don't need to cope with server-side code or worry about writing and embedding JavaScript code in the hosting page. The control takes care of everything and exposes an intuitive programming model through which you can control the script callback mechanism.

The ABC of Controls Script Callbacks
The ASP.NET script callback mechanism consists of two key elements: the server-side code that executes in response to a user action and the JavaScript callback code on the client that processes the results generated by the server-side event. In a scenario where a page calls back to itself, like the one I considered in the aforementioned articles, you can attach some ASP.NET-generated script code to a page button that performs a postback that's invisible to the user. Because the target of this request is the current page, the page posts to itself, similar to how it would in an ordinary postback event, though with an abbreviated page lifecycle. The page must implement the ICallbackEventHandler interface so that a method with a predefined signature can be called to generate results for the client.
So how does the scenario differ when a control triggers the out-of-band call? In this case, the target URL of the "invisible" postback is the URL of the page that hosts the caller control. The control must implement the ICallbackEventHandler in order to provide a method that generates some results for the client. Likewise, the control is responsible for injecting in the hosting page any JavaScript code that is needed to process results and refresh the page.
A callback-enabled control is simply a control that implements the ICallbackContainer and ICallbackEventHandler interfaces, both of which have one method. The ICallbackContainer interface has a method to return the script code that triggers the remote call; the ICallbackEventHandler interface provides the server-side code to execute during the call. ICallbackEventHandler is the same interface that a callback-enabled page must implement. The declaration for a sample custom control that implements callback interfaces is shown in the following code:
public class CallbackValidator : WebControl, 
    INamingContainer, ICallbackContainer, ICallbackEventHandler
In the implementation of the ICallbackContainer interface you may need to place a call to the page's GetCallbackEventReference method to obtain a correct JavaScript call to start the server event. I'll return to this later.

The CallbackValidator Control
To understand callback-enabled server controls, let's take a look at an example of a custom validator control powered by ASP.NET script callbacks. In ASP.NET, validation controls are used to check and verify the input of the form fields defined within a Web page. The validator is a server control that inherits from the BaseValidator class which, in turn, inherits from Label.
Each validation control references an input control located elsewhere in the page. When the page is about to be submitted, the contents of any monitored server control is passed to the validator for further processing. Each validator performs a different type of verification. For example, the CompareValidator control compares the user's entry against a fixed value using a comparison operator such as less-than, equal-to, or greater-than. The RangeValidator ensures that the user's entry falls within a specified range whereas the RegularExpressionValidator validates the user's entry only if it matches a pattern defined by a regular expression.
Normally, validation takes place on the server. However, ASP.NET also provides a complete client-side implementation for most validation controls and allows the user to write custom client-side script for the rest. This allows DHTML-enabled browsers, such as Microsoft® Internet Explorer version 4.0 and later, to perform validation on the client as soon as the user tabs or clicks out of a monitored input field. In many cases, client-side validation is powerful enough to detect many significant errors and notify users. For example, a RequiredFieldValidator control verifies that the given field is not left empty. There is no need to post back to the server to verify the current value.
If client-side validation is turned on, the page won't post back until all the input fields contain valid data. In order to run secure code and to prevent malicious and underhanded attacks, you should still validate data on the server; server-side validation is always performed by the validator controls even if client-side validation is also performed. Besides, not all types of validation can be accomplished on the client. In fact, if you need to validate against a database, there's no choice but to post back to the server. And this is just where the rub lies.
A regular postback involves the page as a whole. The entire view state is uploaded, the entire page is processed, and the same large response is generated, downloaded, and rendered. Wouldn't it be nice if you could issue an out-of-band, optimized request to the server and check the state of only the controls under validation?
In ASP.NET there's no such a control. So let's write one that I'll name CallbackValidator. CallbackValidator is a custom ASP.NET 2.0 control I built to demo how a control can implement out-of-band calls to the host page and handle the event itself on the server.
When I embarked on this project, I actually had a not-so-ambitious objective: my goal was simply to modify the CustomValidator standard control. For the record, the CustomValidator control employs programmatically defined validation logic to check the validity of the user's entry. You use this approach when the values to check against are not known beforehand. The original intention of the CallbackValidator control was to offer a way to perform server-side validation without posting back the whole page. I was halfway finished with modifying my control when I realized that with no significant extra effort I could have had a custom button-like control capable of validating a number of input fields on the server without posting back the whole page. This behavior is what the CallbackValidator control is all about.
Before I delve into the control's nuts and bolts, take a look at Figure 1. The Submit button on this page just posts all the values to the server the usual way. In practice, values will be processed on the client and if all of them pass, the control passes to the server where all control input will be validated using the server-side validation code, if any. The Validate button triggers an out-of-band call to the Web server and validates only the specified input controls. When it returns, you know which values have passed validation by the server. In Figure 1, for example, you'll know whether the user ID is already taken before you try to submit the rest of the data.
Figure 1 Input Form with a Callback-Enabled Validation 
Figure 2 shows the source code of this page. As you can see, it contains an HTML server form, a few textboxes (each bound to a standard validation control), and an instance of the custom CallbackValidator control. This control is actually responsible for creating and displaying the Validate button.

How the Control Works
The CallbackValidator control inherits from WebControl and implements the INamingContainer interface. In addition, it implements the ICallbackContainer and ICallbackEventHandler interfaces for callback support.
The ICallbackContainer interface requires a method, GetCallbackScript, declared like so:
string GetCallbackScript(IButtonControl buttonControl, string argument)
GetCallbackScript takes two arguments. The first is a reference to the page's control that is expected to trigger the callback. The second argument (a string) represents any context the caller wants to pass to the method to help with the construction of the output. As the name suggests, the GetCallbackScript method prepares and returns a string with the JavaScript function call to attach to the specified button control to trigger the remote call.
The button control argument allows you to specify exactly which button in the control's UI you're making the JavaScript call for. The sample CallbackValidator control has just one clickable button; the GridView control has many, one for each link button in the pager or in the header. In ASP.NET 2.0, all controls that act like a button on a form are required to implement a new interface—IButtonControl. The interface is detailed in Figure 3 and is implemented by the following Web controls: Button, LinkButton, and ImageButton. By design, HTML button controls do not implement the interface. Note that in the Microsoft .NET Framework 1.x, the IButtonControl interface exists (albeit with a radically different set of members) only for Windows® Forms button controls.
The second interface required by a callback-enabled control is ICallbackEventHandler—the same interface required on pages that support script callbacks. The interface consists of one method:
string RaiseCallbackEvent(string eventArgument)
The method receives input values in the form of a string, does some server-side work, and returns its response again in the form of a string. What matters here is that both input and output data can travel packed as strings; the real content and format of the strings is up to the coder.
Before I discuss the implementation of the CallbackValidator control, take a look at Figure 4, which illustrates how the control fits in the page's HTTP handler that processes requests for ASPX resources. The CallbackValidator control looks like a button with some script code attached. The script code is just what its GetCallbackScript method returns. When clicked, the button (Validate) fires the background postback sending view state, current input values, plus a couple of custom strings named CALLBACKPARAM and CALLBACKID. The former contains the input value for RaiseCallbackEvent as created in the body of the GetCallbackScript method, and CALLBACKID serves to identify the server-side object to handle the server event. Once on the server, the page's HTTP handler that picks up the request from the ASP.NET runtime tries to locate a control with that ID that implements ICallbackEventHandler. If successful, the control's RaiseCallbackEvent method is invoked and its output returned to the client. If the CALLBACKID targets the page, the HTTP handler sees if the page implements the interface and then proceeds as usual.

Building the Control
CallbackValidator is a composite control whose user interface consists of a simple pushbutton. You can easily extend this aspect of the control by adding a few properties to set the style of the button—link, push, image, or whatever. The text to be shown on the button is set by the ButtonText property. A collection property named ControlsToValidate gathers the IDs of all page validators to be tested on the server during the callback. The property is implemented as a StringCollection type and is empty at the beginning. The code in Figure 5 only lets you add control IDs at run time, which you would typically do in the Page_Load event:
void Page_Load(object sender, EventArgs e) {
   CallbackValidator1.ControlsToValidate.Add("valUserId");
   CallbackValidator1.ControlsToValidate.Add("valEmail");
}
Note that the collection class doesn't persist its contents to the view state. For this reason, you must always reinitialize it when a request comes in. Note also that you should add validation controls, not input controls, to the collection. During the remote call, the CallbackValidator control will invoke the Validate method on associated controls and store the responses for the client callback. The CallbackValidator control works with existing validators making an out-of-band call to test them all; it's not actually a new type of validator itself.
As you can see in Figure 5, the CallbackValidator control creates a Button control and attaches some code to its OnClientClick property. OnClientClick is a new property introduced in ASP.NET 2.0 to add a JavaScript call to the HTML onclick event. In ASP.NET 2.0, the following two lines of code are completely equivalent:
button.Attributes["onclick"] = js; // ASP.NET 1.x; still works in 2.0

button.OnClientClick = js; // ASP.NET 2.0
The code to associate with the validate button is obtained through a specific method wrapped in the ICallbackContainer interface. Note that as of Beta 1, the use of the ICallbackContainer interface is not mandatory, but using it does help to keep code neat and clean. I didn't use it in last month's example and it is not even mentioned in the MSDN documentation for Beta 1 that discusses script callbacks. Nonetheless, ASP.NET controls that benefit from script callbacks (mostly the GridView) implement it. The only component that uses the ICallbackContainer interface is the control itself, meaning that you can easily write a callback-enabled control that doesn't use that interface.
The JavaScript function call that GetCallbackScript returns comes from the following statement:
Page.GetCallbackEventReference(
    this, args, "CallbackValidator_UpdateUI", "null"));
The first parameter (this) indicates the current control and sets the CALLBACKID field in the request being issued. The second parameter (args) is the input string for the server-side RaiseCallbackEvent method. The third parameter is the name of the JavaScript callback function which is used to process the output of the RaiseCallbackEvent method. Finally, the fourth parameter is null in this case, but represents a JavaScript object to be passed as the context of the callback function.
The CallbackValidator control must ensure that the JavaScript callback is defined in the hosting page and must make the decision about the format and contents of the args parameter. There is just one type of information the RaiseCallbackEvent implementation needs from its client caller: the list of validators to test. Here's the code that concatenates all validators' IDs in a pipe-separated string:
int i = 0;
StringBuilder sb = new StringBuilder("");
foreach (string s in ControlsToValidate) 
{
   if (i>0) sb.Append("|");
   sb.Append(s);
   i++;
}
string args = String.Format("'{0}'", sb.ToString());
An example of JavaScript code bound to the Validate button in Figure 2 might look like the following:
WebForm_DoCallback(
    'ctl00$PageBody$CallbackValidator1',
    'valUserId|valEmail',
    CallbackValidator_UpdateUI,
    null,
    null);
Note that the ID of the CallbackValidator control is mangled by the server so that it can uniquely identify every control on the page.

Working Around State Issues
As in Figure 4, the request posted back contains a few input fields. Aside from the aforementioned CALLBACKID and CALLBACKPARAM fields, the request includes a few more input fields. More precisely, it includes all the input fields in the form, plus the two specific to the callback operation. In other words, the view state is posted back along with the current values of the input fields (textboxes, dropdown lists, and so forth).
The page HTTP handler restores the view state and posted values before it checks the callback status of the request and figures out which object (Page or control) will have RaiseCallbackEvent called. In light of this, you may assume that the code defined in the RaiseCallbackEvent method will execute in a consistent and updated state. In particular, you may assume that all validators invoked by the RaiseCallbackEvent method of the CallbackValidator control will test the current values of their bound input controls. As the section title may suggest, this is not the case. Take a look at the code of RaiseCallbackEvent in Figure 6.
The method retrieves the validator control and invokes its Validate method. The method does its job (what exactly depends on the type of the validator) and sets the IsValid property to either True (valid) or False (invalid). Next, the RaiseCallbackEvent method builds its response to the client page. The return string is a pipe-separated collection of strings, each with the following form:
controlID:valid (0/1):message:tooltip
The first token is the client ID of the control that is the fully qualified ID that takes into account any mangling due to Master Pages and naming containers. The second token is 0 or 1 depending on the value of IsValid. The third token is the message the validator would display after a full postback. This corresponds to the validator's Text (default) or ErrorMessage property. I also force a * string if both are empty. By design, Text is expected to contain some text to simply mark the field as invalid. ErrorMessage, instead, provides a more detailed explanation of the error. If the CallbackValidator's ShowDetailedInfo property is true, I use the ErrorMessage string as a tooltip, as shown in Figure 7.
Figure 7 Validation Error Message 
So where's the state-related hassle? This machinery works great on paper, but not with real values. While debugging, I realized that the results of the validation tests were completely unreliable. For example, the User ID textbox is designed to accept anything but "Dino" and empty strings. Well, it works great with regular postbacks, but not if callback validation is used. Some well-placed breakpoints showed that all textboxes retain their original values and ignore what you may have typed before attempting to validate. The problem is not with the view state, but with posted values. The page machinery works great as usual; it just doesn't receive what I perceived to be the correct values from the client.
If you scroll the HTML source code of a page that uses ASP.NET callbacks, you see that upon page loading a call is made to a JavaScript function named WebForm_InitCallback. This function is part of the ASP.NET 2.0 infrastructure and is injected into the page through the WebResource.axd system handler. A look at the source code of this function is in order. (See last month's column for details on how to get it.) Basically, WebForm_InitCallback builds the body of the POST request when the page loads. The body of the page is a string (its name is __theFormPostData) filled with the contents of the view state and all of the input fields in the form. The code is correct; however it executes at a time I wasn't expecting! The content of the input fields is collected at load time and is not updated with user-supplied values when the post back takes place. That's why the server state appeared to be incorrect. To work around this issue, I simply repeated the call to WebForm_InitCallback before starting the out-of-band call (see Figure 6). Note that this is in fact the expected behavior rather than any sort of bug. The argument against the system calling WebForm_InitCallback before the out-of-band call is for scenarios where the user wants to perform the callback in the context of the data that was originally sent down from the server.

JavaScript Files as Embedded Resources
To top off the column, let me discuss a nifty technique that greatly simplifies JavaScript code injection in ASP.NET 2.0 custom controls. The technique also works in ASP.NET 1.x. The idea is simple: write your JavaScript code in regular JS files and add them to the project as embedded resources. (Set the Build Action property in the Visual Studio® .NET Properties window). Also, prefix the resource name with the component's namespace. Next, when you need to use the script in the code, do what the EmbedScriptCode method does in Figure 6. You use a bit of reflection, but you gain a lot in terms of code maintenance and readability.

Conclusion
ASP.NET script callbacks are an extremely powerful feature that can save time on each page update. Although a server request is issued, the whole page remains intact in the browser's window. The advantage is two-fold. First, the user has the illusion that no postback is necessary and continues reading or working with the page. Second, only a few page fragments are refreshed (using the HTML object model). In the August 2004 and December 2004 columns, I provided in-depth coverage of the basic feature. This month I demonstrated how to implement callbacks in custom controls to provide more flexibility in the controls you build.

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


Dino Esposito is a Wintellect instructor and consultant based in Italy. Author of Programming ASP.NET and his newest book Introducing ASP.NET 2.0 (both from Microsoft Press), he spends most of his time teaching classes on ASP.NET and ADO.NET and speaking at conferences. Get in touch at cutting@microsoft.com or join the blog at weblogs.asp.net/despos.

Page view tracker