Developing applications using the Web ADF - ASP.NET Integration  

AJAX and the ASP.NET 2.0 Callback Framework

 



Interaction with a Web application can be initiated via a synchronous page postback or an out-of-band postback, known as a client callback, from the client to the server.  The default ASP.NET Web page model uses synchronous page postbacks, which are usually triggered on the client by submitting an html form.  During a page postback, the Web page and controls are recreated and a new version of the entire Web page is rendered on the client.  In addition, most of the application logic is present on the server-side.   Unfortunately page postbacks often introduce a great deal of processing overhead which can decrease performance.  Since the entire page must be reconstructed via a synchronous request to the server, the client must wait for a response to continue working.  On the other hand, client callbacks can improve performance and enhance the end user experience when working with a Web application.   Callbacks utilize a set of technology standards commonly referred to as AJAX (Asynchronous JavaScript and XML). 

AJAX includes: Client callbacks can be synchronous or asynchronous.  In either case, the browser creates a new connection to send the callback to a remote server, thus the callback is out-of-band.  The contents of the entire page do not need to be submitted, so the page lifecycle for a callback skips events associated with rendering page contents on the server.   In addition, sending an asynchronous callback to a server permits an end user to continue working in the client application while the request is processed.  When the response is returned, the appropriate content in the Web page is updated without refreshing the entire page.  The diagrams below illustate the difference between synchronous and asynchronous communication between a client application and a server.


Synchronous                                                                  

        


Asynchronous

         

The ASP.NET 2.0 implementation of client callbacks uses the Client Callback Manager to provide an extensible callback framework.  After initial page load, subsequent requests to server-side code are made by a client-side component, without refreshing the entire Web page.  The page runs a modified version of its normal life cycle (see diagram below) where the page is initiated and loaded, but the page contents are not rendered.   Instead, a special method in the server-side code is invoked, which processes the callback request content, then returns a value to the browser that can be read by JavaScript function.  The JavaScript function uses technology inherent to the browser (e.g. DOM, DHTML) to update Web page content dynamically.  The Web page continues to stay live while the request is being processed.

The diagram below illustrates the difference between the page lifecycle sequence of events between a synchronous page postback and a client callback.  The Page.IsPostback property will return true for both request types.  The Page.IsCallback property will return true only when the request is a client callback.



 
Developing an ASP.NET 2.0 page that uses client callbacks is a two-step process.  First, create the server-side code that will be invoked by the client.  Second, create the client-side code to invoke the callback request and process the response.  Note that the message in the callback request and response is always a string.  The content and format of the string is up to the developer.  The request usually includes a string to tell the server which action to perform and some user provided data.  The response usually contains content to be rendered on the client or a set of data to trigger further actions.  

Working with Callbacks in an ASP.NET Web application 

The following outline highlights the basic steps used to implement client callbacks in an ASP.NET 2.0 Web page.  In this example, the current time on the Web server is returned and rendered in the client browser:
  1. Implement the System.Web.UI.ICallbackEventHandler.

    The ICallbackEventHandler interface can be implemented on a page or a Web control.   The interface contains two key methods: RaiseCallbackEvent(string EventArgs) and GetCallbackResult().  RaiseCallbackEvent() receives the message in the callback request sent from the client.  It can be designed to parse the message and determine what server-side logic will be executed.  Once the server-side code is finished, it creates a string of values to be sent to the client using the GetCallbackResult() method.   Here is an implementation example of both methods in the code-behind page Default.aspx.cs.  The eventArgument will be updated via a callback request from the client.  This is discussed in greater detail below. 

    [C#]
    public partial class Default : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler
    {
    
    	string returnstring;
    
    	string ICallbackEventHandler.GetCallbackResult()
    	{
    		return returnstring;
    	}
    
    	void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
    	{
    		if (eventArgument == "getservertime")
    		{
    			returnstring = DateTime.Now.ToString();
    		}
    	}
    
    
  2. Call the GetCallbackEventReference method on the Page class.

    The GetCallbackEventReference method creates a JavaScript string in the client Web page to start the callback.  The usage and method parameters are listed below:

    Usage: GetCallbackEventReference(control, argument, clientCallback, context, clientErrorCallback, useAsync);
    					
    Parameter Name Description
    control The control or the page which implements ICallbackEventHandler.
    argument Name of a client-side JavaScript variable. References the string sent to the RaiseCallbackEvent method via the eventArgument parameter.
    clientCallback Name of the client-side JavaScript function which will receive the result of a successful server event.
    context Name of a client-side JavaScript variable. Usually used to determine the content of the message (argument) in the callback request. The value of the variable will be stored on the client as the context parameter associated with a callback.
    clientErrorCallback Name of the client-side JavaScript function which will receive the callback result when an error occurs.
    useAsync Boolean to determine whether a synchronous or asynchronous callback is made to the server.

    Here is an example of the method used in code.  The sCallBackFunctionInvocation member variable is a public string, global to the Page class:

    [C#]
    public string sCallBackFunctionInvocation;
    
    protected void Page_Load(object sender, EventArgs e)
    {
        sCallBackFunctionInvocation = Page.ClientScript.GetCallbackEventReference(this,
          "message", "processMyResult", "context", "processMyError", true);
    }
    					
    At runtime, when the Web page is first loaded, the GetCallbackEventReference method generates a JavaScript string that contains the WebForm_DoCallback function with the parameters listed above.  The next step will discuss adding a reference to this function in client-side code. 
  3. Create the client-side code to trigger the callback and process the response.

    Implementing System.Web.UI.ICallbackEventHandler and calling GetCallbackEventReference will add something similar to the following script tag in your aspx page at runtime:
    <script src="/WebAppName/WebResource.axd?d=TqQApA1CcEIyShhLjzTczw2&t=632657807109074470" type="text/javascript">
    </script>
    

    WebResource.axd is a new HTTP Handler in ASP.NET 2.0 that enables Web page and Web control developers to download resources that are embedded in an assembly.   The System.Web.dll contains a JavaScript resource that contains the WebForm_DoCallback function.  The format of this URL is WebResource.axd?d=encrypted identifier&t=time stamp value .  The "d" refers to the requested Web resource and is an encrypted string of the assembly name and resource name.  The "t" is the timestamp for the requested assembly, which can help in determining if there have been any changes to the resource.   At runtime, the JavaScript resource is downloaded to the client.  

    In many cases, callbacks within a browser are managed using the XMLHttpRequest object.  More specifically, the ASP.NET 2.0 Callback Framework includes JavaScript content to support callbacks.   The JavaScript function which initiates and manages callbacks in the client browser is WebForm_DoCallback.  It creates an ActiveX object, Microsoft.XMLHTTP for Internet Explorer browsers or a native XMLHttpRequest object for other browsers to manage HTTP communication with a Web application on the server.  The Microsoft.XMLHTTP object is packaged with the Microsoft XML Document Object Model, part of the MSXML set of components.     

    The following code provides an example of the HTML content in an aspx page configured to work with callbacks.  The edits to the code involve two steps:

    1. Add an HTML element and a JavaScript function to create a callback request.  In the HTML code below, the click event of an HTML button triggers a call to the JavaScript function getServerTime, which in turn calls WebForm_DoCallback.  The message variable is set to 'getservertime' which is used by the server to determine which action to execute.  The server variable <%=sCallBackFunctionInvocation%> is translated to WebForm_DoCallback('__Page', message, processMyResult, context, postMyError, true) at runtime.
    2. Add two JavaScript functions to process the callback response and update the page.  The processMyResult function takes the callback response string and updates the text content of a div tag in the HTML page.  Note, this happens dynamically so other objects in the page are not redrawn.  The postMyError function receives the callback message if an error was thrown on the server.  In this case, it pops up an alert box.
    <html>
    <head>
        <title>Untitled Page</title>
        <script  language="javascript" type="text/javascript">
            function getServerTime()
            {
               var message = 'getservertime';
               var context = 'Page1';
               <%=sCallBackFunctionInvocation%>
            }
    
            function processMyResult(returnmessage, context){
                 var timediv = document.getElementById('timelabel');
                 timediv.innerHTML = returnmessage;
            }
    
            function postMyError(returnmessage, context){
                alert("Callback Error: " + returnmessage + ", " + context);
            }
        </script>
    </head>
    <body>
        <form id="form1" runat="server">
            <input type="button" value="Get Server Time" onclick="getServerTime();" />
            <div id="timelabel"></div>
        </form>
    </body>
    </html>
    


    The following diagram illustrates a callback event at runtime.  The green circles indicate the order in which events occur to initiate and process the callback.  A short description for each event is provided below:


     


    1. After the Web page loads, the onClick event of an HTML button is triggered which calls the user-defined getServerTime JavaScript function.

    2. The getServerTime function sets the message and context variables to be sent to the server and calls the ASP.NET 2.0 defined WebForm_DoCallback function to create and send the callback request.

    3. A new XMLHttpRequest object is created to send and receive the asynchronous call to\from the server.

    4. The XMLHttpRequest object posts the HTTP request to the server containing the message.  On the server, the RaiseCallbackResult method parses the argument (message) and executes some business logic - in this case, it converts the time on the server to a string.  The GetCallbackResult method passes this string back to the XMLHttpRequest object waiting on the client. 

    5. The ASP.NET 2.0 WebResource for callbacks directs the callback response string to the registered callback response function, the user-defined processMyResult function.

    6. The processMyResult function uses the content of the callback response string to dynamically update HTML in the Web page.  In this case, it inserts HTML into an existing <div> tag to display the server time.