Working with callback results


In this topic


About working with callback results

The ArcGIS Web Application Developer Framework (ADF) contains a framework to manage the synchronization of server-client content in an Asynchronous JavaScript and XML (AJAX) environment. This framework, the callback results framework, consists of server-side classes and control properties and client-side Web ADF JavaScript logic. During user interaction with a Web application, the state of a Web ADF control and other content on the server often changes. Web ADF controls communicate changes in their state on the server with Web ADF controls in the browser via callback results. A callback result is a Web ADF-specific JavaScript Object Notation (JSON) formatted string generated on the server, often by Web ADF controls. 
Custom callback results can also be created using the Web ADF CallbackResult class. All Web ADF controls have a CallbackResults public property that references a collection of CallbackResult instances in a Web ADF CallbackResultCollection. Collections of callback results can be managed using the CallbackResultCollection class, which means you can add, remove, and convert the entire collection to a string. Web ADF callback results are explicitly designed to be processed by the Web ADF JavaScript function ESRI.ADF.System.processCallbackResult().
Some Web controls also maintain their own processCallbackResult() function for control-specific processing of callback results. The Web ADF callback results framework makes it easier for you to use managed server-side classes to modify both Web ADF and non-Web ADF content in the client browser. The following diagram highlights the components of the callback results framework on the client and server:
Web ADF controls always use callback results to update client-side content in the browser regardless of whether you explicitly create or manage them. For example, when calling the Zoom method on a Map control, the Map control generates a callback result. The following diagram illustrates the initial Web request, which calls the Zoom() method on the Map control (server-side), then the Map control packages callback results in the Web response:
The Map control is a script control, so it is represented on the client as a JavaScript object and on the server as a .NET Server control.
Although the technique for packaging callback results differs depending on the AJAX pattern you use for your page (callback or partial postback), callback result content and processing callback results by Web ADF JavaScript on the client remain the same.
If a Web ADF control initiates a Web request, it automatically packages its callback results in a Web response. In some cases, you may want to change or interact with controls or elements on the page other than the Web ADF control that initiated the request. This can include both Web ADF and non-Web ADF content. To use the Web ADF callback results framework to update client content, you must package custom messages in a CallbackResult class and ensure it is processed on the client by the Web ADF JavaScript processCallbackResult() function.
For Web ADF content, there are a number of inherent relationships between Web ADF controls where callback results are copied to the Web ADF control that packages the callback results for the response (see the Internal callback result management in Web ADF controls section for more details). If the Web ADF control you want to change is not covered by a predefined relationship, you must explicitly manage its callback results. This means you must copy the callback results for the Web ADF control you changed (via the CallbackResults property) into the callback results collection of the Web ADF control responsible for generating the callback results in the Web response.
The diagrams and code sample in this section provide an example of the Web ADF Map control initiating a request and packaging callback results in a response and the Toc control needing to be refreshed to reflect changes in the state of the map (for example, if a new map resource item was added).
The Toc control's callback results are copied to the Map’s callback results collection via the CopyFrom() method as shown in the following code:
[C#]
... < new map resource item added > Toc1.Refresh();
Map1.CallbackResults.CopyFrom(Toc1.CallbackResults);
The following diagram shows the callback results being combined and returned in the response and provides a brief view of the underlying format of CallbackResults and CallbackResultCollection:

CallbackResultCollection object

The ability to manage callback results in and between Web ADF controls depends on the capabilities of the CallbackResultCollection class. The CallbackResultCollection class provides a convenient means for managing multiple CallbackResult objects. While each Web ADF control maintains a CallbackResultCollection (accessible via the CallbackResults property), you can also create a CallbackResultCollection for your own use. The following table lists a number of methods on the CallbackResultCollection object:
Method
Description
Add
Adds an individual CallbackResult instance to a collection. Useful when creating custom CallbackResult instances and adding them to the existing callback collection for a Web ADF control.
CopyFrom
Copies an entire CallbackResultCollection to another collection. Useful when updating a Web ADF control whose callback results are not automatically included in a response. Copy its callback results into the Web ADF control that's responsible for generating the callback results in a response.
ToString
Converts a CallbackResultCollection into a string with the appropriate formatting for the processCallbackResult() function to parse and utilize its content. Useful in cases where the control responsible for generating the callback results for a response is not a Web ADF control, or when the AJAX pattern requires callback results be explicitly packaged as a string.

Custom callback results

To work with non-Web ADF content on your page, you can use either AJAX pattern-specific techniques or the Web ADF callback result framework. For example, to update a ListBox or GridView using the partial postback pattern, you can use an UpdatePanel. If you leverage the callback result framework, a custom CallbackResult object may suit your needs.
The CallbackResult class defines a set of arguments that enable you to work with almost any Hypertext Markup Language (HTML) content on the page by utilizing client-side technologies and the browser document object model (DOM) to locate and interact with elements on the page. For example, custom JavaScript code can be executed on the client as needed. The following table defines a set of static methods on the CallbackResult class that can be used to interact with browser content:
CallbackResult static method
Description
CreateSetContent
Sets the outerHTML property of an HTML element
CreateSetInnerContent
Sets the innerHTML property of an HTML element
CreateSetImageSource
Sets the src property of an image element
CreateJavaScript
Executes JavaScript on the client
CreateIncludeJavaScript
Includes JavaScript on the client
CreateIncludeStyleSheet
Includes a CSS style sheet on the client
The following code example shows how to execute a line of JavaScript code associated with a custom callback result using the CreateJavaScript static method. A Map control (Map1) generates the callback results for a Web response, so the custom callback result is added to Map1's callback results collection. When this code is executed at run time and processed by the Web ADF JavaScript, a message box displays in the browser containing the phrase "Hello World":
[C#]
string javascriptString = "alert('Hello');";
CallbackResult customCallbackResult = CallbackResult.CreateJavaScript
    (javascriptString);
Map1.CallbackResults.Add(customCallbackResult);
Each custom CallbackResult instance is designed to be processed by the Web ADF JavaScript processCallbackResult() function from the ESRI.ADF.System.js library. The processCallbackResult() contains the logic to process the custom CallbackResult content as shown in the following code:
[JavaScript]
if (action ==  = 'javascript'){
    var method = function(){
        try{
            eval(params[0]);
        }
        . . .
    }
    else if (action ==  = "content"){
        var o = $get(controlID);
        if (o){
            o.outerHTML = params[0];
        }
        . . .
    }
    else if (action ==  = "innercontent"){
        var o2 = $get(controlID);
        if (o2){
            o2.innerHTML = params[0];
            validResponse = true;
        }
        . . .
    }
    else if (action ==  = "image"){
        var o3 = $get(controlID);
        if (o3){
            o3.src = params[0];
        }
        . . .
    }
    else if (action == 'include'){
        var id = params[0];
        var elm = (id ? $get(id): null);
        . . . if (elm){
            elm.parentNode.removeChild(elm);
        }
        document.getElementsByTagName('head').item(0).appendChild(elm);
        . . .
    }
For more information on the use of custom callback results and the CallbackResult class, see the following samples:

Internal callback result management in Web ADF controls

In some cases, a Web ADF control can generate callback results without requiring an explicit call to refresh the control on the server. This is often the case with the Map control. Merely changing map extent or scale causes the Map control to automatically update its callback result collection. In other cases, an explicit call to refresh is required, such as when layer visibility changes or a resource is added or removed. An explicit call to refresh the Map control is not always necessary. In many cases, you do not need to explicitly copy callback results from one Web ADF control to another. A number of inherent relationships between Web ADF controls are listed as follows:
  • When a Toolbar control is buddied to a Map control, any command action on the Toolbar copies the Map's callback results to the Toolbar's callback results collection. If the command changed the Map, the callback results are added to the Toolbar callback results, which generates the Web response. The same applies to a PageLayout control if a Toolbar control is buddied to it.
  • When a Toc control is buddied to a Map control, a NodeChecked event copies the Map's callback results to the Toc's callback results.
  • When the Map and Toc controls contain a scale dependent layer, a ScaleChanged event copies the Toc's callback results to the Map's callback results.
  • When a ScaleBar control is buddied to a Map control, the ScaleBar’s PreRender event copies the ScaleBar’s callback results to the Map’s callback results.
  • When a MapCopyrightText control is buddied to a Map control, adding or removing a map resource item copies the MapCopyrightText’s callback results to the Map’s callback results.
  • When a Magnifier control is buddied to a Map control, changing the extent of the map or initializing the tiling scheme copies the Magnifier's callback results to the Map’s callback results. The FloatingPanel.Refresh() method adds the callback results for all child Web ADF controls to the FloatingPanel’s callback results collection.
  • When a TaskResults control is buddied to a Map control, execution of a task copies the Map’s callback results to the TaskResults control. The TaskResults' callback results are then added to the task’s callback results, which is responsible for generating the callback response. If you manually copy the Map's callback results to the TaskResults' callback results, they are duplicated.
  • The TaskResults control contains a set of preconfigured ContextMenus. During the ItemClicked event on these ContextMenus, the callback results collection from the TaskResults and Map controls are added to the ContextMenus' callback results.

Exceptions for non-Web ADF controls

In general, some controls that are added to the page but are not visible or do not contain content, do not add an HTML element when the page is rendered in the client browser. Since callbacks are designed to work with the browser’s DOM to update content dynamically, the callbacks need an element (object) with which to work. The GridView control exhibits this behavior.
If the GridView has been added to a page but is not visible or is empty, no complimentary object on the client is available. When the GridView is populated on the server and needs to be rendered on the client via a callback, you need to provide a location to render the content using the browser's DOM. One accepted solution is to use a div element on the client to wrap the GridView. When the GridView needs to be updated via a callback, the innerHTML of the div can be completely replaced, and the location and style of the GridView is maintained on the page, regardless of its visibility.