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

Disabling a User Interface Element During a Partial Page Postback

By Scott Mitchell


Introduction


When using Microsoft's ASP.NET AJAX framework and an UpdatePanel whose ChildrenAsTriggers is set to True (the default), anytime a user interface element within the UpdatePanel would normally cause a full page postback, a partial page postback is performed instead. For example, clicking a Button Web control or selecting a different item from a DropDownList control whose AutoPostBack property is set to True normally causes a full page postback, but if these controls are within an UpdatePanel, a partial page postback occurs instead. But what happens if a partial page postback is taking a while to complete and the user triggers the partial page postback again? Or what if during this lull she clicks some other Button in the same UpdatePanel, thereby causing a second partial page postback to ensue?

If a partial page postback is made from the same UpdatePanel while a partial page postback is ongoing, the first partial page postback is aborted and the second postback commences. Aborting a partial page postback simply means that the ASP.NET AJAX framework on the browser no long listens for a response back from the server for that request. It does not stop processing on the server, or rollback any state changes that may have occurred on the server. Consequently, if on a partial page postback you are inserting records into a database or making some other state change, if a user clicks a Button in an UpdatePanel to instigate a partial page postback, but then clicks the same Button again while the partial page postback is still ongoing, there will be two duplicate records inserted in the database.

There are a couple of ways to prevent the user from resubmitting a partial page postback while it's still ongoing. The most effective way, in my opinion, is to "freeze" the frame by overlaying the screen with a <div> element. (See the final demo in the article, Providing Visual Feedback with the UpdateProgress Control.) Another option is to disable the user interface element that triggered the postback during the partial page postback lifecycle. This prevents the user from resubmitting the partial page postback. Read on to learn more!

The Need for Disabling the User Interface During a Partial Page Postback


The download available at the end of this article includes a demo named NoDisabling.aspx that illustrates the default behavior. The demo consists of an UpdatePanel control containing two Button Web controls. On the first page load, a Session variable named NumberOfClicks is set to 0:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
   If Not Page.IsPostBack Then
      Session("NumberOfClicks") = 0
   End If
End Sub

In the Buttons' Click event handlers this Session variable is incremented and the Button that was clicked along with the value of the Session variable are displayed in the Results Label control. What's more, both Click event handlers sleep for five seconds to add an artifical delay in the partial page postback. This delay is present to mimic the time it might take to perform the partial page postback in a real-world setting. The Click event handler for Button1 follows:

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
   Session("NumberOfClicks") += 1

   Results.Text = String.Format("Button 1 was clicked... The Buttons have been clicked {0:d} times", Session("NumberOfClicks"))

   Thread.Sleep(5000)
End Sub

A recent article of mine, Performing Client Actions in Response to Partial Page Postbacks, showed how to execute client script at various stages during the partial page postback's lifecycle. If you haven't yet read this article, please do so before continuing here. In the article I showed how to build a client-side event logger that displays a message as each client-side event of the PageRequestManager object is raised. The demo available for download includes such functionality.

To see the need for disabling the user interface during a partial page postback, visit the demo page through a browser. Click the first button to instigate a partial page postback. The event log dislays two entries:

  • initializeRequest
  • beginRequest
The next event, endRequest, is not displayed until the response is returned from the server (or if the partial page postback is aborted). During the partial page postback, click the first button again. This starts the second partial page postback. In the first stage of the second partial page postback (initializeRequest), the first partial page postback is aborted. This behavior is evidenced by the event log in the screen shot below. Note that the first two events, initializeRequest and beginRequest, occurred at 11:08:14, and were triggered by clicking "Button 1" for the first time. Two seconds later, I clicked "Button 1" again. This triggered the third event log entry, initializeRequest, at 11:08:16. Because the first postback is still outstanding, it is automatically aborted. The fourth event log entry, endRequest, indicates the conclusion of the first partial page postback. And the fifth event log entry (beginRequest) signals the second stage of the second partial page postback.

What's important to understand is that aborting a postback causes the client API to stop listening for a response, but it does not stop processing on the server or rollback any state changes. This is made clear by the output displayed in the Results Label at the conclusion of the second partial page postback. Even though the first partial page postback was aborted, the Session variable has been incremented twice.

In cases where the partial page postback performs some sort of state modification it is prudent to prevent the user from re-triggering the partial page postback when the partial page postback is ongoing. This article examines one approach for accomplishing this functionality: by disabling the user interface element that caused the partial page postback.

Determining the User Interface Element that Triggered the Partial Page Postback and Disabling It


As we've already seen, whenever a partial page postback commences, the PageRequestManager raises a series of client-side events. The first one is initializeRequest. Following that, the beginRequest event is raised. The beginRequest is passed an args object that includes information on what user interface element caused the partial page postback. Specifically, this information can be retrieved via args.get_postBackElement(). Once we have a reference to the user interface element that caused the postback, we can disable it by setting its disabled property to true:

function PageRequestManager_beginRequest(sender, args)
{
   var postbackElem = args.get_postBackElement();
   postbackElem.disabled = true;
}

This code disables the user interface element at the start of the partial page postback (before the actual HTTP request is transmitted from the client to the server). However, this code alone is not sufficient - we need to enable the user interface element once the partial page postback completes.

Re-Enabling the User Interface Element that Triggered the Partial Page Postback


The PageRequestManager raises its endRequest event at the conclusion of a partial page postback, regardless of whether the partial page postback completed successfully, ended from an error, or was canceled or aborted from client-side script or by user action. Therefore, it makes sense to re-enable the user interface element in the endRequest event handler.

Unfortunately, the endRequest event handler is not passed a reference to the control that triggered the partial page postback. Therefore, we need to save this information in a page-level variable. The following JavaScript illustrates how to accomplish this. Note the page-level variable, uiId. This variable is assigned the id attribute of the element that caused the partial page postback in the beginRequest event handler. It is then used in the endRequest event handler to get a reference to the element and set its disabled property to false.

var uiId = '';



function PageRequestManager_beginRequest(sender, args)
{
   var postbackElem = args.get_postBackElement();
   

uiId = postbackElem.id;


   postbackElem.disabled = true;
}


function PageRequestManager_endRequest(sender, args)
{
   $get(uiId).disabled = false;
}

Note that in the endRequest event handler I use the $get(id) function to get a programmatic reference to the element specified by the ID value uiId. $get(id) is a function that is part of the ASP.NET AJAX framework's client API. It serves as a shortcut to the Sys.UI.DomElement class's getElementById function.

Testing the Disabled UI Functionality


The download available at the end of this article includes a demo named Disabling.aspx that has the same user interface as NoDisabling.aspx, but implements the client-side disabling/enabling logic we just discussed. The following screen shot shows the page shortly after "Button 1" has been clicked. Note that "Button 1" is disabled - it does not respond to clicks until it is re-enabled.

After the partial page postback completes, "Button 1" is re-enabled and can be clicked again to perform another partial page postback.

Stopping Other Partial Page Postbacks


Disabling the user interface element that triggers the partial page postback ensures that the same control won't initiate another postback, thereby aborting its ongoing request. But what if another element in the same UpdatePanel triggers a partial page postback? For example, what happens if, in the Disabling.aspx demo, the user clicks "Button 1" and then, during the postback, clicks "Button 2"? Clicking "Button 2" aborts the "Button 1" postback and then initiates the "Button 2" partial page postback logic.

To prevent this we can either disable the entire user interface in the event of a partial page postback (instead of just "Button 1"). See the final demo in the Providing Visual Feedback with the UpdateProgress Control article for such an example. Another option is to programmatically prevent a partial page postback from starting if there is an ongoing one.

The sender object passed into the initializeRequest event handler has a function named get_isInAsyncPostBack() that returns a Boolean value indiciating if there is an ongoing partial page postback. To permit only one partial page postback at a time, check this function and cancel the current request if it returns true. The following JavaScript snippet illustrates how to accomplish this:

function PageRequestManager_initializeRequest(sender, args)
{
   if (sender.get_isInAsyncPostBack())
   {
      args.set_cancel(true);
      alert('The page is currently serving a request. Please wait until this request completes, then try again.');
   }
}

In addition to canceling the requested partial page postback, the above code also displays an alert explaining to the user that their current request cannot be processed until the ongoing request finishes. The following screen shot shows this functionality in action. "Button 1" has been clicked and is in the midst of a partial page postback. Because of the script we added in the previous section, the button is disabled. If the user clicks "Button 2" during the partial page postback, an alert box is shown and the partial page postback request from "Button 2" is canceled.

Conclusion


In some circumstances, a partial page postback performs some action on the server that affects the state of the web application. For such partial page postbacks it's usually important that the user does not repeatedly cause the same partial page postback. For example, if the partial page postback inserts a record into the database, triggering the same partial page postback multiple times - by, say, clicking a Button repeatedly - may result in duplicate database entries. To remedy this you can either disable the entire user interface by means of an overlaid <div> element or you can more selectively disable the user interface element that triggered the partial page postback for the duration of the postback. This article examined the latter approach.

Happy Programming!

  • By Scott Mitchell


    Further Readings:


  • Providing Visual Feedback with the UpdateProgress Control
  • Performing Client Actions in Response to Partial Page Postbacks
  • Managing the User Experience in AJAX
  • Attachments:


  • Download the Demo Code Used in this Article

  • Article Information
    Article Title: ASP.NET.Disabling a User Interface Element During a Partial Page Postback
    Article Author: Scott Mitchell
    Published Date: June 11, 2008
    Article URL: http://www.4GuysFromRolla.com/articles/061108-1.aspx


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