Callbacks came up in a discussion I was having while brainstorming some v-next ideas. I think callbacks have the potential of enabling a whole new genre of smart Web applications. This feature happens to be a personal favorite of my mine. In one sense, callbacks are a much improved reincarnation of remote scripting, which I worked on as part of my first project upon joining Microsoft and the Visual InterDev team way back in '97.
So far in ASP.NET, postbacks have been the primary mechanism to incrementally update the UI. But this has some associated problems: back button enabling, scrolling, refreshing etc. They are appropriate when their use is in sync with the
user's semantic model - for example, when submitting a form, and not the framework's semantic model. On the other hand, incremental work and UI updates within the same page rarely qualify as a scenario for postbacks. For example, when a tree view node is expanded, the end user is least expecting a new page to show up. Quite the contrary is true... he is actually expecting an interactive display where the node expands in-place without disturbing anything else on the page.
"Callbacks" is a fancy name for what is essentially an out-of-band request to the server. Rather than posting a form or a page and receiving a brand new and complete page in response, some intelligent client script can package up data for processing, ask the server to process it and then consume the result. This intelligent script can then seamlessly blend that result into the page's existing rendering. While this is happening, the page remains completely interactive. So the user experience is improved on two counts: the page remains interactive while the communication with the server happens, and second, the new result is shown without flicker, loss of current position, or spurious navigation. Things become less choppy allowing Web applications to emulate some of the rich client application behaviors more closely.
When we started implementing the TreeView control for the next version of ASP.NET, the first step was to put in-place a framework that would allow us to build a more realistic user interface model. We built this framework in a general way so other controls could use it just as well, resulting in what is known as the Callbacks feature. I have a very simple example, a
PerformanceCounterLabel control that uses callbacks to continually update the display of a performance counter value without refreshing or posting the page. The control demonstrates how you implement ICallbackEventHandler to use the callback framework.
The basic idea behind callbacks isn't completely new. I think the innovation here is really about how we integrated this into the page lifecycle. This integration stems from our fundamental requirement, which is so fundamental in fact, that as far as I recall, it has remained unspoken for the most part. The requirement is to allow the page developer to remain oblivious of the callbacks. It is the responsibility of the framework and server control developers to make magic happen. First and foremost this implies that the page developer continues to write a single page and that secondly, they continue to write code in event handlers. How this was accomplished is described below.
The framework that we provide has two parts. The first is a script library that implements the logic to perform asynchronous HTTP requests back to the server, receive the response, and then invoke the script callback rendered by the control. Our implementation uses XMLHTTP, which is available in IE as well as in Mozilla. We package up the data you want to send down to the server, the target of the callback (the unique ID of the control) as well as the view state of the page (you'll see why in a moment) in the __CALLBACKPARAM, __CALLBACKID and __VIEWSTATE request variables respectively and perform an HTTP request.
On the server, the page starts executing its lifecycle, as though it were a POST request because of the view state presence. Very soon however, it also notices the __CALLBACKID variable, which not only identifies the target of the callback, but also puts the page into Callback. The page now executes a trimmed down lifecycle involving the Init, Restore ViewState and Load phases, followed by an invocation of the target control's ICallbackEventHandler implementation, and then immediately disposing the page, thereby skipping the rendering phase.
So we satisfied the first part of the fundamental requirement. The callback request is made to the same page, allowing the page developer to put all their logic into a single page, and code as if nothing has changed. This was made possible by having the page lifecycle be aware of callbacks, so it could do the right things, or rather not run through the logic that isn't meaningful. The next part of the requirement was to enable the event-based programming model. It is likely that page developer will access properties or method of server controls in their events, and that server controls themselves will want to interact with each other during the callback request as well. This is where the view state comes in. Just like in the postback world, the view state restores the page to the state it existed in during the last request, callbacks also use view state to restore the page to their previous state before the Page_Load and the ICallbackEventHandler implementation is called. This makes the event-based model work despite the stateless environment. Furthermore, this allows a server control author to also remain mostly oblivous of callbacks as well - they can just assume their control is in the right state and perform their logic. The framework takes care of the details!
Here's a
slide deck that contains an animation of the request/response loop and the page lifecycle for both the postback and callback models.
I think we've just scratched the surface when it comes to actually using callbacks in Whidbey with a ton of scenarios yet to be realized... imagine asynchronous validators validating by executing server-side validation logic, background fetching of data with client-side paging, switching between multiple views of a control etc. etc. I'd love to hear what ideas people have for using callbacks to enhance their controls, as well as any comments you have on the sample.
Posted on Friday, 6/25/2004 @ 8:38 PM
| #
ASP.NET