Developing Ajax-Enabled Controls and Components: Periodic Refresh Pattern

Ajax-enabled components that use the Periodic Refresh pattern periodically poll the server for changes. This article develops an Ajax-enabled custom control named AjaxNotifier that will show you how to use the Periodic Refresh pattern to develop your own Ajax-enabled controls.

AjaxNotifier is an Ajax-enabled control that periodically polls the server for the latest posted notification and displays the notification in a pop-up dialog, shown in Figure 1. As this figure shows, the pop-up dialog exposes two pieces of information about a notification: the source of the notification (notifier) and the content of the notification.

Figure 1

Here is how the workflow goes:

  1. AjaxNotifier uses DOM and JavaScript to retrieve the latest notification ID that the user has seen. The notification IDs include the complete information needed to determine the order in which the notifications are issued. This could be a timestamp; that is, the creation date of the notification.
  2. AjaxNotifier uses the ASP.NET 2.0 client callback mechanism to make an asynchronous callback to the server to download the XML document that contains the information about the latest notification. The client-side code also passes the notification ID of the latest notification that the user has seen to the server so the server can send the next notification back to the client.
  3. AjaxNotifier then uses XML, DOM, and JavaScript to dynamically retrieve the required data from the XML document and to display the information in the pop-up dialog.

The AjaxNotifier control derives from the WebControl base class and implements the ICallbackEventHandler interface. The control overrides the following methods of the WebControl class:

  • OnPreRender
  • AddAttributesToRender
  • TrackViewState
  • SaveViewState
  • LoadViewState

Deriving from WebControl

Listing 1 presents the implementation of the OnPreRender method.

Listing 1: The OnPreRender method

protected override void OnPreRender(EventArgs e)
{
   DetermineRenderClientScript();
   if (renderClientScript)
   {
      string js = Page.ClientScript.GetCallbackEventReference(
                  this,
         "GetNotificationId('"+ClientID+"')",
         "AjaxNotifierCallback",
         "'" + ClientID + "'", true);
      string js2 = "function DoCallback () {" + js + ";}";

      Page.ClientScript.RegisterClientScriptResource
         (typeof(AjaxNotifier),
         "CustomComponents.AjaxNotifier.js");
      Page.ClientScript.RegisterClientScriptBlock(typeof(AjaxNotifier),
         typeof(AjaxNotifier).FullName + "DoCallback", js2, true);
      Page.ClientScript.RegisterStartupScript(typeof(AjaxNotifier),
         typeof(AjaxNotifier).FullName + "WebDoCallback", js,true);
   }
   base.OnPreRender(e);
}

OnPreRender registers three script blocks. The first script block references the CustomComponents.AjaxNotifier.js embedded resource:

Page.ClientScript.RegisterClientScriptResource(typeof(AjaxNotifier),
        "CustomComponents.AjaxNotifier.js");

Chapter 26 “Developing Ajax-Enabled Controls and Components: Client-Side Functionality” in the book Professional ASP.NET 2.0 Server Control and Component Development (Wrox, July-2006, ISBN: 0-471-79350-7) covers the embedded resources in detail. The AjaxNotifier.js script file contains the JavaScript functions that the AjaxNotifier control uses. In this article, I discuss these JavaScript functions in detail.

The second script block contains the code for the DoCallback JavaScript function. Notice that this function runs the JavaScript code that the GetCallbackEventReference method of the ClientScript property of the page returns. As covered in Chapter 27 “Developing Ajax-Enabled Controls and Components: Asynchronous Client Callback” in the book Professional ASP.NET 2.0 Server Control and Component Development (Wrox, July-2006, ISBN: 0-471-79350-7), this JavaScript code includes a call to a JavaScript function that contains the code that makes the asynchronous client callback to the server:

string js = Page.ClientScript.GetCallbackEventReference(
        this,
        "GetNotificationId('"+ClientID+"')",
        "AjaxNotifierCallback",
        "'" + ClientID + "'", true);
string js2 = "function DoCallback () {" + js + ";}";

The third script block includes a call to the JavaScript function that contains the code that makes the asynchronous client callback to the server. Notice that OnPreRender uses the RegisterStartupScript method to register this script to request the page to render the script at the bottom of the page. This means that the first asynchronous call is made right after the page is loaded. You’ll see the significance of this later in this section.

    Page.ClientScript.RegisterStartupScript(typeof(AjaxNotifier),
    typeof(AjaxNotifier).FullName + "WebDoCallback", js,true);

Listing 2 contains the code for the AddAttributesToRender method of the AjaxNotifier control.

Listing 2: The AddAttributesToRender method

protected override void AddAttributesToRender(HtmlTextWriter writer)
{
  base.AddAttributesToRender(writer);

  if (renderClientScript)
  {
      CssStyleCollection col;
      writer.AddAttribute("notificationId", "0");
      if (dialogStyle != null)
      {
         col = dialogStyle.GetStyleAttributes(this);
         writer.AddAttribute("dialogStyle", col.Value);
      }
      if (headerStyle != null)
      {
         col = headerStyle.GetStyleAttributes(this);
         writer.AddAttribute("headerStyle", col.Value);
      }
      if (itemStyle != null)
      {
         col = itemStyle.GetStyleAttributes(this);
         writer.AddAttribute("itemStyle", col.Value);
      }
      if (alternatingItemStyle != null)
      {
         col = alternatingItemStyle.GetStyleAttributes(this);
         writer.AddAttribute("alternatingItemStyle", col.Value);
      }
   }
}

The dialog that the AjaxNotifier pops up handles everything on the client side including rendering, moving, resizing, and font-adjustment when the dialog is resized. Therefore, this pop-up dialog isn’t a server control. Chapter 27 shows you how you can expose the CSS style attributes of a client-side component such as this pop-up dialog as top-level properties of the Ajax-enabled control itself.

AjaxNotifier exposes the same top-level properties that the AjaxDetailsDialog from the previously mentioned Chapter 27 exposes. The AjaxNotifier control also overrides the TrackViewState, SaveViewState, and LoadViewState methods to manage the states of these top-level properties across page postbacks. This is thoroughly discussed in Chapter 27 in the same book.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read