The Web ADF contains a framework to manage the synchronization of server-client
content in an asynchronous (AJAX) environment. This framework, termed 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 will often change. 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, JSON
(JavaScript Object Notation) 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
property which 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. In essence, the Web ADF’s callback results framework makes it
easier for you, the developer, 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 will 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 will
generate 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, thus it is represented on the
client as a JavaScript object and on the server as a .NET Server
control.

Important note: Although the technique for packaging callback results will
differ depending on the AJAX pattern you choose for your page (callback
versus partial postback ), callback result
content and processing callback results by Web ADF JavaScript on the client
will remain the same.
If a Web ADF control initiates a Web request, it will automatically package its
callback results in a Web response. In some cases, a developer may want to
change or interact with other controls or elements in the page besides the Web
ADF control that initiated the request. This may include both Web ADF and
non-Web ADF content. To use the Web ADF callback results framework to update
client content, a developer must package custom messages in a CallbackResult
class and make sure 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 section on internal
callback result creation below for more details). If the Web ADF control you
want to change is not covered by a pre-defined 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 code and diagrams
below provide an example where the Web ADF Map control initiates a request and
packages callback results in a response and the Toc control needs to be
refreshed to reflect changes in the state of the map (e.g. a new map resource
item was added). The Toc's callback results are copied to the Map’s callback
results collection via the CopyFrom() method. The diagram shows the actual
callback results being combined and returned in the response and provides a
brief view of the underlying format of a CallbackResult and
CallbackResultCollection.
CallbackResults example code
[C#]
... <new map resource item added> Toc1.Refresh(); Map1.CallbackResults.CopyFrom(Toc1.CallbackResults);
CallbackResults process

Actual CallbackResult string content

The ability to manage callback results within and between Web ADF controls
hinges on the capabilities of a CallbackResultsCollection. 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 a CallbackResultCollection object you may find
beneficial:
| CallbackResultCollection Method Name | Description |
|---|---|
| Add | Used to add individual CallbackResult instances to a collection. Often useful when creating custom CallbackResult instances and adding them to the existing callback collection for a Web ADF control. |
| CopyFrom | Used to copy an entire CallbackResultCollection to another collection. Often useful when you need to update a Web ADF control whose callback results are not automatically included in a response. Merely copy its callback results into the Web ADF control responsible for generating the callback results in a response. |
| ToString | Used to convert a CallbackResultCollection into a string with the appropriate formatting for the processCallbackResult() function to parse and utilize its content. Often useful in cases where the control responsible for generating the callback results for a response is not a Web ADF control -or- the AJAX pattern requires callback results be explicitly packaged as a string . |
So far, this section has discussed existing CallbackResults and
CallbackResultCollections associated with Web ADF controls. In many cases, you
may want to work with non-Web ADF content in your page. For non-Web ADF
content, you have a choice of using 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 do
choose to leverage the callback result framework, a custom CallbackResult
object should suit your needs. The next section focuses solely on custom
CallbackResult objects and capabilities.
Custom callback results
The CallbackResult class defines a set of arguments that enable you to work
with almost any html content in the page by utilizing client-side technologies
and the browser DOM (document object model) to locate and interact with
elements in the page. For example, custom JavaScript code can be executed on
the client as needed. The table below defines a set of static methods on the
CallbackResult class which can be used to interact with browser
content.
|
CallbackResult
Static Method |
Description |
|---|---|
| CreateSetContent | Set the outerHTML property of an html element. |
| CreateSetInnerContent | Set the innerHTML property of an html element. |
| CreateSetImageSource | Set the src property of an image element. |
| CreateJavaScript | Execute JavaScript on the client. |
| CreateIncludeJavaScript | Include JavaScript on the client |
| CreateIncludeStyleSheet | Include a CSS style sheet on the client |
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 function processCallbackResult() in the ESRI.ADF.System.js library. The processCallbackResult() contains the following logic to process the custom CallbackResult content:
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);
. . .}
Internal callback result management in Web ADF controls
In some cases, a Web ADF control may 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 will
automatically cause the Map control to 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. It's important to be
aware that 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. Listed below are a number of inherent relationships
between Web ADF controls:
- When a Toolbar is buddied to a Map, any command action on the toolbar will copy the Map's callback results to the Toolbar's callback results collection. So if the command changed the Map, the callback results are already added to the Toolbar callback results which will generate the Web response. The same applies for a PageLayout if a Toolbar is buddied to it.
- When a Toc is buddied to a Map, a NodeChecked event, will copy the Map's callback results to the Toc's callback results. When the Map and Toc contain a scale dependent layer, a ScaleChanged event will copy Toc's callback results to the Map's callback results.
- When a ScaleBar control is buddied to a Map, the ScaleBar’s PreRender event will copy the ScaleBar’s callback results to the Map’s callback results.
- When a MapCopyrightText control is buddied to a Map, adding or removing a map resource item will copy the MapCopyrightText’s callback results to the Map’s callback results.
- When a Magnifier control is buddied to a Map, changing the extent of the map or initializing the tiling scheme will copy the Magnifier control’s callback results to the Map’s callback results.
- The FloatingPanel.Refresh() method will add 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, execution of a task will copy the Map’s callback results to the TaskResults control. The TaskResults callback results are then added to the task’s callback results for you, which is responsible for generating the callback response. If you manually copy the Map's callback results to the task's callback results, they will be 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 will be added to the ContextMenu’s callback results.
Exceptions for non-Web ADF controls
In general, some controls that have been added to the page, but
are not visible or do not contain any 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, they
need an element (object) to work with. 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 widely accepted solution to this
problem involves using 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
in the page, regardless of its visibility. Two samples illustrate this
solution: Common_AddCustomTool
and
Common_SelectBufferTool.