ASP.NET 2.0 Callbacks

Create Rich User Interfaces with Client-side Callbacks

ControlFreak

LANGUAGES: VB.NET

ASP.NET VERSIONS: 2.0 (Pre-Release)

 

ASP.NET 2.0 Callbacks

Create Rich User Interfaces with Client-side Callbacks

 

By Steve C. Orr

 

Page postbacks are by far the most common way to pass data between the client and server in an ASP.NET application. The simplicity of this technique is appealing, but the reality is that it s often inefficient and disorienting for the user. If a single value on a Web page needs to be updated, why must the entire page (and the user) suffer through a complete round trip to the server?

 

Even if performance is not an issue for your application, there are plenty of other reasons for ditching postbacks whenever possible. For starters, they are just plain ugly. Even with the speediest servers there are often perceptible flashes and delays while the browser posts back the page, retrieves a slightly modified version of the page, then redraws it completely. You may have also noticed that the Back button doesn t always operate as the user expects in an ASP.NET application. This is entirely due to unnecessary postbacks. There are also scrolling problems; when the user has scrolled the page down and the page posts back, they end up at the top of the page again and must scroll back down manually unless the developer goes out of their way to implement extra code to make it appear as if the page didn t post back.

 

Now that it s been established that postbacks should be avoided whenever possible, what s the best way to get around them?

 

One of the most efficient solutions is to transfer all required data to the browser and use client-side script to manipulate it dynamically without bothering the server at all. While this can be a nice solution for developers who are fluent in JavaScript, large amounts of data frequently prohibit this from being a viable option for dial-up users and other such outliers. In such cases, however, there is one reasonably optimal solution ...

 

Client-side Callbacks

For years it s been possible to use client-side code to call back to the server without posting back the entire page, but the complexity has traditionally scared most developers away. The new client-side callback technology in ASP.NET 2.0 alleviates many of the headaches and reduces the amount of code necessary to make it happen.

 

The classic XMLHTTP callback technology is wrapped by ASP.NET 2.0 callbacks, exposing a relatively simple interface. You may have heard the buzzword AJAX recently, which is a technology nearly identical to XMLHTTP. Certainly in philosophy they are identical, permitting out of band callbacks so Web pages can update themselves fluidly (see Figure 1).

 


Figure 1: ASP.NET 2.0 callbacks wrap standard XMLHTTP technology, which allows Web pages to update themselves fluidly.

 

Automatic Callbacks with TreeViews and GridViews

While you can use ASP.NET 2.0 callbacks with virtually any Web control, the technique is easiest to use with the new GridView and TreeView controls because the technology is built in. Using client-side callbacks with these two controls is as simple as setting a couple properties.

 

The new GridView control can sort and change pages without posting the page back to the server. The GridView control provides an EnableSortingAndPagingCallback property that enables its server-side sorting and paging routines to be called out of band; only the GridView control calls back to the server and refreshes while the rest of the page stays put. Unfortunately, this functionality is broken in Beta 2 of ASP.NET 2.0, but it should be fixed by the final release.

 

The new TreeView control also implements the client-side callback functionality. In fact, the ASP.NET 2.0 client-side callback technology was originally developed specifically for the TreeView control. Luckily for us, the developers had enough foresight to design it in a generic way so it could be used with other controls, as well.

 

TreeView nodes can retrieve their child nodes from the server and expand dynamically, without requiring a full page refresh. To enable this functionality, the EnableClientSideScript and PopulateNodesFromClient properties of the TreeView control must be set to True, and the PopulateOnDemand property of the applicable tree node(s) must also be set to True. Additionally, the TreeView s server-side TreeNodePopulate event must be populated with code that retrieves the node data, places the data into a node structure, and, finally, adds the node structure to the ChildNodes collection. The node structure can be created by adding TreeNode objects to the ChildNodes collection of the parent TreeNode. Figure 2 contains a simplified version of such code; Figure 3 shows the page in action.

 

Sub TreeView1_TreeNodePopulate(ByVal sender As Object, _

 ByVal e As System.Web.UI.WebControls.TreeNodeEventArgs) _

 Handles TreeView1.TreeNodePopulate

   Select Case e.Node.Value

      Case "Software"

          Dim NewNode As New TreeNode

          NewNode.Text = "Antivirus"

          e.Node.ChildNodes.Add(NewNode)

      Case "Hardware"

          Dim NewNode As New TreeNode

          NewNode.Text = "Keyboards"

          e.Node.ChildNodes.Add(NewNode)

   End Select

End Sub

Figure 2: The TreeView control can call back to the server to retrieve the data necessary to expand tree nodes, then place code in the server-side TreeNodePopulate event to add the nodes dynamically. It can then update its own user interface without requiring the page to post back.

 


Figure 3: The child nodes in this TreeView control were retrieved dynamically at run time by client-side code calling back to the server, thus avoiding a costly page postback.

 

Roll Your Own Callbacks

It s sure handy to have client-side callback functionality implemented automatically in the GridView and TreeView controls, but what about all the other Web controls? With a moderate amount of effort, any Web control can be enhanced with client-side callback functionality.

 

The first step is to put the necessary client-side pieces in place. In most cases, some kind of client-side control will need to trigger the event. It s important to not choose a control that causes a postback, because this will negate the client-side callback. So a button Web control would be a bad choice, but an HTML button works just fine. The runat= server attribute is necessary to attach a client-side event to the button at run time from server-side code:

 

 

The button won t do anything until it s wired up with the appropriate code to call back to the server, receive the result, and display the result. The code in Figure 4 does exactly that.

 

Protected Sub Page_Load(ByVal sender As Object, _

 ByVal e As System.EventArgs) Handles Me.Load

 'Define JavaScript functions that will recieve the result

 Dim sCallBack As String = _

   "function MyCallBack(result, context){alert(result);}"

 Dim sErrCallBack As String = _

   "function MyErrCallBack(result,context){alert(result);}"

 'Output the JavaScript functions to the page

 Page.ClientScript.RegisterClientScriptBlock(Me.GetType, _

   "MyCallBack", sCallBack, True)

 Page.ClientScript.RegisterClientScriptBlock(Me.GetType, _

   "MyErrCallBack", sErrCallBack, True)

 'Attach button's client event to the JavaScript functions

 btn.Attributes("OnClick") = _

  Page.ClientScript.GetCallbackEventReference(Me, _

  "'Parm'", "null", "MyCallBack", "MyErrCallBack", True)

 If Not Page.IsPostBack Then

   'Outputs the time the page was initially rendered

   Response.Write("Page Rendered at " & Date.Now.ToString)

 End If

End Sub

Figure 4: This code attaches JavaScript functions to the client-side button that permits it to call back to the server and display the result.

 

The code starts by defining a JavaScript function that will be called with the result of the server s response. It also defines a similar JavaScript function that will be called in the event of an unexpected error. In the second code block these events are actually output to the page via the new ClientScript property of the Page object. By collecting related functions into a single place and adding quite a few new functions, this new property makes managing client scripts easier than it was in ASP.NET 1.x.

 

In the third code block of Figure 4, the button is wired up to perform the call back to the server. The GetCallBackEventReference method is used to make this happen. This function accepts several parameters, as defined in Figure 5.

 

Parameter

Type

Description

control

System.Web.UI.Control

The page or control that s implementing the callback reference.

argument

String

Optionally, a string parameter may be passed from the client to the server-side function.

clientCallback

String

The name of the client-side function that will receive the result of a successful callback.

context

String

The name of the client-side function that will be called before the call back to the server.

clientErrorCallback

String

The name of the client-side function that will be called if there is an error attempting to call back to the server.

useAsync

Boolean

Specifies whether the callback should be synchronous or asynchronous.

Figure 5: GetCallBackEventReference parameters.

 

The final step is for your server-side code to implement the ICallbackEventHandler interface. Its associated RaiseCallbackEvent is the server-side function that gets called by the client-side script; Figure 6 shows an example. Before this function gets called, the page state gets instantiated in a fairly normal way. That is, ViewState, Session, control values, and all the other forms of server context are filled so you can use them as you would in any standard page postback. (This perhaps has slightly more overhead than calling a Web service, but the tradeoff is that the logic can be kept inside the applicable page, thereby simplifying future maintenance.)

 

Partial Class MyPage

 Inherits System.Web.UI.Page

 Implements ICallbackEventHandler

 '(Page_Load event listed in Figure 4)

 Public Function RaiseCallbackEvent(ByVal eventArgument _

    As String) As String Implements _

    System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent

    Return "The server time is " & Date.Now.ToString

 End Function

End Class

Figure 6: Pages that support client-side callbacks must implement the ICallbackEventHandler and its associated RaiseCallbackEvent function.

 

The RaiseCallbackEvent function accepts a string parameter and returns a string parameter. What gets put in these strings is entirely up to you. These parameters could contain simple text, numeric characters, XML, comma-delimited text, empty strings, or virtually anything imaginable that can be represented with text.

 

Keep in mind that the user won t see any visual changes you make to controls from within this function because HTML is not rendered back to the client. For visual changes to happen after a client-side callback, they must be done using client-side code.

 

Also keep in mind that if you have multiple controls on a page that use callbacks, they will all call to the same RaiseCallbackEvent. It s up to you to sort out which control is calling back and what it wants.

 

Figure 7 shows the fully functional program in action. The server time is displayed directly on the page when the page originally renders. When the user clicks on the button, the page does not post back nor refresh, but it does call back to the server to retrieve the current server time and display it in a message box.

 


Figure 7: The server can be contacted for updated information at any time without requiring the page to reload. In this example, the page retrieves the current time from the server.

 

If you view the source of the page you ll notice some hidden fields that are implanted by ASP.NET to help implement the feature. You needn t worry about these because it s all handled automatically. You ll also notice a script reference that ASP.NET uses to implement the XMLHTTP operations that are happening behind the scenes. The reference looks a bit like this:

 

 

Future Compatibility

The code snippets in this article were developed with Visual Studio 2005 Beta 2. It s possible that there could be some syntax changes before the final release. Additionally, it s been said that ASP.NET 2.0 callbacks will support browsers beyond only Internet Explorer, although that s not yet the case in Beta 2.

 

The new GridView and TreeView controls have first-class callback support. It s too bad Microsoft didn t build such high-quality callback support into the rest of the Web controls, but at least a callback solution is now feasible if you re willing to jump through a few coding hoops.

 

Client-side callbacks certainly hold a lot of promise for enriching user interfaces all across the Web. Now users will no longer have to suffer through postbacks that seem (to them) to happen at arbitrary moments. Back buttons can work intuitively once again, and users never again need to be disoriented by having their scroll positions reset. It does take a moderate amount of effort, but your users will love you for it.

 

Steve C. Orr is an MCSD and a Microsoft MVP in ASP.NET. He s been developing software solutions for leading companies in the Seattle area for more than a decade. When he s not busy designing software systems or writing about them, he can often be found loitering at local user groups and habitually lurking in the ASP.NET newsgroup. Find out more about him at http://SteveOrr.net or e-mail him at mailto:[email protected].

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish