One of the challenges that every ASP.NET 1.x web developer faced is that there isn't any native support for script callbacks to server without post-back of the current page. For example, retrieving and presenting the details of a selected employee in a dropdown list without forcing the full page refresh, and this is particularly an expensive call for UI-rich pages. So, how can we handle this?
Thanks to the ASP.NET team, they've built in this feature in ASP.NET 2.0, which allows calls to server events from client code without causing the page to post back and refresh. This is great, but we have to consider 2 facts: Time and Money. For time, we have to wait until ASP.NET 2.0 is released and we can't do anything in the meanwhile. For Money, we may be forced to upgrade Visual Studio .NET IDE from 2002/2003 to 2005 if we can't live without the Visual Studio.NET IDE. More importantly, implementing the script callbacks in ASP.NET 1.x isn't that hard at all. So, what are we waiting for?
Thanks to the extensible architecture of Page Controller framework, it gives developers the flexibility in hand to extend its functionalities, where native support is not sufficed. In this article, I'll walk you through the process of implementing the Script Callbacks Framework, and also provide a simplified but effective framework that you can use in ASP.NET 1.x.
Several objectives have been set for the implementation of Script Callback Framework in ASP.NET 1.x, they are:
- Co-exists with the same functionality provided in ASP.NET 2.0 - avoids the use of similar function or variable name in our implementation.
- Provide a consistent programming model as ASP.NET - similar to the concept of
- Emulate as many functionalities as Script Callbacks Framework implemented in ASP.NET 2.0.
- Provide synchronous and asynchronous callback.
Script Callback Framework consists of 2 core components, which are PageTemplate.cs and ScriptCallback.js files. Each of them takes care of the callbacks processing at server side and client side, respectively. The steps involved in callbacks processing are shown below:
- Server responses - Lookup and invoke the corresponding control to respond accordingly.
- Callback handling - Invoke the client Callback Handler or Error Handler based on the status code returned from the server's response.
PageTemplate derives from
System.Web.UI.Page where it encapsulates most of the processing logic and plays a critical role in the Script Callback Framework. It provides the
For example, the following call to
Server Side code
IncreaseButton.Attributes["onclick"] = GetAsyncCallbackEventReference
Client Side code
<input name="IncreaseButton" id="IncreaseButton"
type="button" value="Increase Value"
PageTemplate overrides the
Render method of
System.Web.UI.Page class to ensure that ScriptCallback.js file and all the script code necessary to perform the callback is correctly referenced within the page or control before rendering to the client. ScriptCallback.js file contains the client code to initialize the callback infrastructure, opens HTTP connection to specified remote ASP.NET Page for callback processing, as well as invokes the corresponding Callback Handler or Error Handler after receiving the result from the server.
WebForm_DoSyncCallback contained in ScriptCallback.js file to callback to the specified remote ASP.NET Page for processing. Internally, it uses a COM object to issue an HTTP POST or GET command to the specified target URL. This COM object comes with Internet Explorer v5.0 or above, and it is an old acquaintance of many developers:
var xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");
The HTTP verb is GET or POST depending on the size of the data to be sent. If the size exceeds 2KB, a POST command is used. The HTTP request consists of three logical elements:
__SCRIPTCALLBACKPARAM, and posted data. The
__SCRIPTCALLBACKID value contains the ID of the control to be invoked (the event target parameter), whereas
__SCRIPTCALLBACKPARAM carries the input parameter for the server-side stub method.
PageTemplate overrides the
OnInit method of
System.Web.UI.Page class to determine if the current request is Postback or Callback mode. It looks for a
__SCRIPTCALLBACKID entry in the
Request collection. If so, it sets the public
IsCallback property to true and concludes that a callback invocation is being made. In the
OnLoad method, it first calls the
base.OnLoad method to ensure all the controls including those dynamically created controls are properly initialized. If it's a callback, it then invokes the
HandleClientCallback function to further process the request.
Internally, it uses the value obtained from
__SCRIPTCALLBACKID entry, which is the ID of the control to be invoked. It looks for the specified control in the
Controls collection and checks to see if the referenced control implements the
IClientCallbackEventHandler interface (which could be the page itself). If the
Control implements the required interface, the
PageTemplate invokes the
RaiseClientCallbackEvent method on the interface, and prepares the response from the results of the call.
IClientCallbackEventHandler interface has just one method with the following signature:
string RaiseClientCallbackEvent(string eventArgument);
eventArgument parameter for the method is retrieved from the
Request collection of posted values. The string representation of the input data is contained in an entry named
PageTemplate uses different status codes to notify client script code about the status of callback processing at server. The status code used here has different meaning than those used in the standard HTTP
STATUS_CODE. The table shown below lists down the 4 possible status codes and their meaning:
|404||Unable to find the specified control|
|500||Internal Error (Unknown Error)|
|501||The specified control does not implement the |
Note: The status code is appended into a custom HTTP Header entry named "
Once a callback operation has completed, the client script will be notified to check the status code returned from the custom HTTP Header entry named "
__SCRIPTCALLBACKSTATUS". It invokes the registered Callback Handler if the status code is "200". Otherwise, the registered Error Handler is invoked to complete the job.
Using the code
With Script Callback Framework in place, developing a Page that makes use of script callbacks is as easy as the few steps listed below:
- Implement the
IClientCallbackEventHandler interface on any control, which intends to support the callback. The control can be
UserControl as well as any Server Controls.
- Write the server-side code in the
- Assign a unique ID to every control that supports
IClientCallbackEventHandler interface either declaratively (HTML) or programmatically (Code).
GetSyncCallbackEventReference function to the control's event. When invoked, initiate and handle the callbacks operation asynchronously or synchronously. Please look at the Limitation section if
System.Web.UI.Page or its derivative is used as the callback target.
System.Web.UI.Page or its derivative cannot be used as the first input parameter for
GetSyncCallbackEventReference functions because the system is unable to find out their ID. The workaround is that you should declare a variable of type
System.Web.UI.HtmlControls.HtmlForm, and its name must match the
ID used in the Page's HTML source, and use this variable as the first input parameter to the aforementioned functions.
<form id="Form1" method="post" runat="server"></form>
protected System.Web.UI.HtmlControls.HtmlForm Form1;
IncreaseButton.Attributes["onclick"] = GetSyncCallbackEventReference
In short, you can use callbacks to update individual elements of a page, such as a
Label or a
Panel, provide different views of the same data, download additional information on demand, or auto-fill one or more fields. To merge the server-side generated values with the existing page, you typically use the Page's DHTML object model. You give each updateable HTML tag a unique ID and modify its contents using the
innerHTML property or any other property and method the DOM supplies.
Last, but not least, I've included a sample, available from the link at the top of this article, that demonstrates the capability of Script Callback Framework.
Points of Interest
Throughout the numerous testing on Script Callback Framework, I found that
Microsoft.XMLHTTP COM object caches the result of each call by its requested URL and post data. No connection will be opened to the requested URL if the same requested URL and post data have been used before. However, the numbers of cache items is unknown to me.
Script callbacks allow you to perform callbacks to the server without refreshing the whole page, which gives users the illusion that everything is taking place on the client. Once again, I have presented the Script Callback Framework which is a simplified version of code that will be completely built when ASP.NET 2.0 is released. You might as well get the functionality you want today, and you'll be ahead of the curve in understanding this similar concept in ASP.NET 2.0 tomorrow.