To read the article online, visit http://www.4GuysFromRolla.com/articles/012109-1.aspx

Periodically Updating the Screen and Web Page Title with ASP.NET AJAX

By Scott Mitchell


Introduction


Developers using Microsoft's ASP.NET AJAX framework can efficiently and interactively retrieve data from the web server using the ASP.NET AJAX client API, a bit of JavaScript, and Web services that support script access. Last week's article, Building Interactive User Interfaces with Microsoft ASP.NET AJAX: Retrieving Server-Side Data Using Web Services, looked at how to create such Web services and how to call them from an ASP.NET AJAX application. With a sprinkle of JavaScript, This functionality can be implemented to provide a user interface that periodically updates, presenting pertinent information to the user without the need for the user to refresh her browser.

Consider the following scenario: you are building a website that serves as a front-end for a work item database. The database contains tasks assigned to an employee; throughout the course of the day new tasks may be assigned to an employee by other workers, by automated processes, or by other means. When an employee logs onto the site he sees a hyperlink that lists the number of open work items in the upper left corner of every page, and clicking that link takes him to a page that lists the open work items in his queue. After completing a work item he closes it, which removes it from his list of open work items. In a typical web application the number of open work items in the upper left corner would only be refreshed when the user performed a postback, manually refreshed the page, or visited a new page. Wouldn't it be nice if that count of open work items would interactively update as new work items assigned to the user entered the queue?

This article looks at how to build such an interactive user interface by using the ASP.NET AJAX framework, script-enabled Web services, and a few lines of JavaScript, building upon the techniques discussed in Retrieving Server-Side Data Using Web Services. A complete, working demo is available for download at the end of this article. Read on to learn more!

An Look at the Work Item Website and Pre-AJAX "Open Work Items" Display Area


The download available at the end of this article includes a demo illustrating the concepts touched upon in this article. The demo is a very simple data-driven web application that is designed to allow users to log on, see their open work items, and, once a work item has been completed, mark it as such. The application uses ASP.NET's Membership system to support user accounts; specifically, the SqlMembershipProvider provider is used and the user accounts are stored in the ASPNETDB.mdf database in the App_Data folder.

The ASPNETDB.mdf database also contains the WorkItems table, which has a record for each work item in the system. As the following schema shows, each WorkItems record has a unique identifier (WorkItemID), a description (WorkItem), is associated with a particular user (UserId), and has the date and time the work item was added and completed (if it has been completed).

WorkItems
NameData TypeNotes
WorkItemIDintPrimary key, IDENTITY
WorkItemnvarchar(50) 
UserIduniqueidentifierForeign key to aspnet_Users.UserId
DateAddeddatetimeThe date/time the record was added to to the table
DateCompleteddatetimeCan be NULL; if specified, the date/time the work item was completed

The web application consists of three pages:

  • Default.aspx - the site's home page
  • Login.aspx - the login page
  • WorkItems.aspx - displays the currently logged on user's list of open and completed work items
The WorkItems.aspx page, shown in the screen shot below, had a button for adding one to five new work items along with two GridView controls. The top GridView displays open work items (those whose DateCompleted value is NULL) and completed work items (those whose DateCompleted value is not NULL). The open work items GridView includes a CLOSE LinkButton in each row that, when clicked, closes the work item by setting the corresponding record's DateCompleted value to the current date and time.

The WorkItems.aspx page.

The three ASP.NET pages in the website all use the same master page, Site.master, which defines the common look and feel - the text "Updating the Screen and Title Demo" at the top of the page, the "Home" and "Your Work Items" links along the left column, and the "Welcome back, Username" message in the upper right. There's also an area in the upper left corner that lists how many open work items there are for the current user. It's circled in the above screen shot, and reads: "3 open work items." This text is actually a link, clicking it whisks the user to the WorkItems.aspx page. Moreover, this text in is the master page and therefore appears on every content page, including Default.aspx and other, future pages.

Imagine that a user visits Default.aspx at 3:00 PM and she has three open work items. She will see the message, "3 open work items" in the upper left corner of the screen. Now, imagine that she minimizes her browser and starts working on non-work item tasks and that, during that time, two new work items are added to her queue. When she brings her browser back to the foreground the page has not been updated, it still reports that there are three open work items. Granted, if she manually refreshes the screen at this time she'll see that there are now really five open work items, but she must remember to do this. Some web applications "force" a period refresh by adding a <meta> element to the page to force a refresh every so often, but this approach can disorient users and can be very frustrating in pages where the user may be busy entering information in textboxes or working with other user input elements on the page, only to have that information lost when the page is automatically refreshed.

A better solution is to use AJAX to interactively refresh the text in the upper left corner. And if the JavaScript that updates the text also updates the page's title to include the number of open work items the user can see the number of current open work items in the task bar when the browser is minimized. The remainder of this article shows how to implement such functionality using the ASP.NET AJAX framework, script-enabled Web services, and a touch of JavaScript.

A High-Level Overview of How the Screen and Title is Periodically Updated


Before we delve into the details of updating the screen and page title with the currently logged on user's open work item count, let's first take a high-level look at the solution. We need some way for the page to contact the server and ask, "How many work items are open for the currently logged on user?", and we need this question to be asked periodically, say once every 30 seconds. Furthermore, when getting the answer to this question we need to display it in the text in the upper left corner and update the page's title.

Last week's article, Retrieving Server-Side Data Using Web Services, showed how to efficiently communicate with the server from JavaScript using the ASP.NET AJAX framework's client-side API. In short, you can create a Web service on the server and make it accessible from client-side script by decorating it with the ScriptService attribute. Moreover, you can create a JavaScript proxy class by registering the script in the ScriptManager's Scripts section. So we already know how to create such a service and call it from JavaScript. But how do you have a service called every n seconds?

JavaScript includes a function named setInterval(code, timeout) that executes code every timeout number of milliseconds. Therefore, we can use this function to call the Web service every 30 seconds (or whatever duration you decide on). For more information on this function (as well as information on a related function, setTimeout), read JavaScript Timers with setTimeout and setInterval.

Updating the work item count text and the page's title is just a matter of a few lines of JavaScript. You can use the Document Object Model (DOM) to programmatically reference an HTML element and then tweak its display via its innerHTML property. A page's title can be read and modified via the document.title property.

Creating a Script-Enabled Web Service for Returning the Number of Open Work Items


The first step is to create a script-enabled Web service that returns the number of open work items for the currently logged on user. Create a new Web service, decorate it with the ScriptService attribute, and then add the following method:

<WebMethod()> _
Public Function GetOpenWorkOrders() As String
   Dim results As Integer = -1

   'Get information about the user
   Dim userInfo As MembershipUser = Membership.GetUser()
   If userInfo IsNot Nothing Then
      Dim userId As Guid = userInfo.ProviderUserKey

      'Get the number of open work items for this user
      Using myConnection As New SqlConnection(ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString)
         Const sql As String = "SELECT COUNT(*) FROM WorkItems WHERE UserId = @UserId AND DateCompleted IS NULL"

         Dim myCommand As New SqlCommand(sql, myConnection)
         myCommand.Parameters.AddWithValue("@UserId", userId)

         myConnection.Open()
         results = Convert.ToInt32(myCommand.ExecuteScalar())
         myConnection.Close()
      End Using
   End If

   Return results
End Function

When the client application calls the Web service it passes along its cookies. Because this website uses forms-based authentication, when a user logs on to the site an authentication ticket is added to the cookies collection so that the user can be identified on subsequent requests. Consequently, we can determine the user calling this Web service (if they have already logged on) by the authentication ticket in their cookies. Of course, we don't need to write any code to inspect a user's authentication ticket; instead, this all happens behind the scenes by the ASP.NET engine. We can get information about the currently logged on user by simply calling Membership.GetUser() or from the User.Identity property.

The above Web service method starts by calling the Membership.GetUser() method. If this method returns Nothing then the person making this Web service call is anonymous. In such a case the method returns a value of -1. But if the user is authenticated then their UserId value is grabbed from the MembershipUser object's ProviderUserKey property and is then used in the SQL query that returns the number of open work items. This count is returned.

To call the script-enabled Web service from JavaScript we need to register the service in the ScriptManager control. (The ScriptManager, as well as the JavaScript we'll be examining next, is located in the master page, Site.master.) The ScriptManager control's declarative markup follows:

<asp:ScriptManager ID="myScriptManager" runat="server">
   <Services>
      <asp:ServiceReference Path="~/Services/WebsiteServices.asmx" />
   </Services>
</asp:ScriptManager>

Calling the Script-Enabled Web Service and Updating the Screen and Title


The following JavaScript function, UpdateOpenWorkItemCount, calls the GetOpenWorkOrders Web service asynchronously and indicates that the GetOpenWorkOrdersOnSuccess and GetOpenWorkOrdersOnFailed functions are to be called on success or on failure, respectively.

function UpdateOpenWorkItemCount() {
   // Call the GetOpenWorkOrders Web Service
   WebsiteServices.GetOpenWorkOrders(GetOpenWorkOrdersOnSuccess, GetOpenWorkOrdersOnFailed);
}

The text - "3 open work items", or whatever the number may be - is displayed by a HyperLink control on the master page named WorkItemCountLink that, when clicked, sends the user to the WorkItems.aspx page.

<asp:HyperLink runat="server" ID="WorkItemCountLink" NavigateUrl="~/WorkItems.aspx" Text=""></asp:HyperLink>

The HyperLink control renders an anchor element (<a>), which can be programmatically referenced via the DOM and its innerHTML property set to change the link's text. The GetOpenWorkOrdersOnSuccess function updates this link text along with the page's title. These areas are only updated if the value returned from the Web service is greater than or equal to zero. (Recall that if the Web service is called by an anonymous user it returns a value of -1. In that case we do not want to update the screen or title.) The code for the GetOpenWorkOrdersOnSuccess function follows:

var originalTitle = document.title;

function GetOpenWorkOrdersOnSuccess(results) {
   // Display results in workItemCount
   if (results >= 0) {
      var workItemCount = document.getElementById('<%=WorkItemCountLink.ClientID %>');
      if (workItemCount) {
         workItemCount.innerHTML = results + ' open work items';

         if (results == 0)
            workItemCount.style.color = 'White';
         else
            workItemCount.style.color = 'Yellow';
      }

      // Update the page's title
      document.title = originalTitle + ' (' + results + ')';
   }
}

Updating the Display On Page Load and Every 30 Seconds After That


The last piece of the puzzle is having the UpdateOpenWorkItemCount function, which calls the Web service and updates the display, invoked on page load and every 30 seconds (or whatever) thereafter. This is accomplished by creating a pageLoad JavaScript function and calling the UpdateOpenWorkItemCount function immediately and then using setInterval so that it's called after every 30 second interval.

function pageLoad(sender, args) {
   // Update the screen display and then have it updated every 10 seconds...
   UpdateOpenWorkItemCount();

   setInterval('UpdateOpenWorkItemCount();', 30000);
}

That's all there is to it! To change the frequency with which the UpdateOpenWorkItemCount function is called, change the setInterval function's second input parameter from 30000 (30 seconds) to whatever value you prefer.

The Screen and Title Updates In Action!


To see the screen and page title updates in action download the web application from the end of this article. Open it in Visual Studio and launch the website. Open two browser instances and log into the site. In one browser instance visit Default.aspx, on the second go to WorkItems.aspx. At this point you should see the number of open work items in the upper left corner. For example, in the screen shot below you can see that there are three open work items.

There are three open work items.

Also note that the number of open work items is shown in the page's title. This appears in the top window bar, the tab, and the task bar.

The open work item count appears in the page's title.

From the second browser instance (WorkItems.aspx), close two work items. Return to the first browser instance (Default.aspx). Do not refresh the page, but wait. Within 30 seconds you should see the text in the upper left corner (and in the page's title) change to reflect that there is now only one open work item. Neat!

The screen and title were automatically updated to reflect that there is now only one open work item!

Happy Programming!

  • By Scott Mitchell


    Attachments:


  • Download the Demo Code Used in this Article

    Further Reading


  • Building Interactive User Interfaces with Microsoft ASP.NET AJAX: Retrieving Server-Side Data Using Web Services
  • Periodically Changing the Title (JavaScript code snippet)
  • JavaScript Timers with setTimeout and setInterval
  • Article Information
    Article Title: ASP.NET.Periodically Updating the Screen and Web Page Title with ASP.NET AJAX
    Article Author: Scott Mitchell
    Published Date: January 21, 2009
    Article URL: http://www.4GuysFromRolla.com/articles/012109-1.aspx


    Copyright 2014 QuinStreet Inc. All Rights Reserved.
    Legal Notices, Licensing, Permissions, Privacy Policy.
    Advertise | Newsletters | E-mail Offers