When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article

ASP ASP.NET ASP FAQs Message Board Feedback
 
Print this Page!
Published: Wednesday, May 28, 2008

Building Interactive User Interfaces with Microsoft ASP.NET AJAX: Performing Client Actions in Response to Partial Page Postbacks

By Scott Mitchell


A Multipart Series on ASP.NET AJAX
Over the past several years web developers have started using JavaScript to make asynchronous postbacks to the web server that only transmit and receive the necessary data; these techniques are commonly referred to as AJAX. Microsoft has released a free AJAX framework for ASP.NET developers named Microsoft ASP.NET AJAX. This article series examines using Microsoft's ASP.NET AJAX framework to build responsive user interfaces.

  • AJAX Basics and Getting Started with Microsoft's ASP.NET AJAX Framework - examines AJAX basics and looks at installing Microsoft ASP.NET AJAX; includes a demo of the UpdatePanel control.
  • Using the UpdatePanel - provides more in-depth and real-world examples of using the UpdatePanel.
  • Providing Visual Feedback with the UpdateProgress Control - shows how to use the UpdateProgress control to display visual feedback to the user when a partial page postback is in progress.
  • Performing Client Actions in Response to Partial Page Postbacks - learn how to execute client-side script in response to events raised by the partial page postback life-cycle.
  • Using the Timer Control - see how to asynchronously update a portion of the screen every n milliseconds.
  • Enabling Bookmarking and the Browser's Back Button - learn how to add history points to an AJAX-enabled web page so that your visitors can use their browsers' Back and Forward buttons and bookmarks.
  • Retrieving Server-Side Data Using Web Services - call Web Services from an ASP.NET AJAX application with a sprinkle of JavaScript.
  • A Look at JSON Serialization - explore the serialization format used by the ASP.NET AJAX Framework when calling Web Services from client-side script.
  • Triggering Full Page Postbacks From An UpdatePanel - learn how to override an UpdatePanel's default behavior and trigger a full page postback.
  • Refreshing An UpdatePanel With JavaScript - see how to refresh the contents of an UpdatePanel via JavaScript.
  • Rebinding Client-Side Events After a Partial Page Postback - discover how to automatically rebind client-side event handlers to HTML elements in an UpdatePanel after a partial page postback.
  • (Subscribe to this Article Series! )

    Introduction


    The previous three articles in this series focused on building AJAX-enabled web applications using server-side techniques and controls. For instance, Using the UpdatePanel examined how to define regions on the page that participate and are updated by partial page postbacks; Providing Visual Feedback with the UpdateProgress Control showed how to use the UpdateProgress control to display feedback during a long-running partial page postback.

    The ASP.NET AJAX Framework also includes a rich client-side library and event model that enables page developers to create and execute client script and event handlers that integrate with the ASP.NET AJAX Framework. This article starts our examination of client-side development with the ASP.NET AJAX Framework. In particular, it examines the client-side PageRequestManager object, which includes methods and events tied to the partial page postback mechanism. In a nutshell, we can use the PageRequestManager object to execute client-side script immediately before or after a partial page postback.

    This article discusses the basics of the client-side PageRequestManager object and includes examples that show how to abort and cancel partial page postbacks as well as how to scroll to a particular location on screen after a partial page postback completes. These working demos are available for download at the end of this article. Read on to learn more!

    - continued -

    The Client-Side Events of a Partial Page Postback


    As discussed in Using the UpdatePanel, whenever a Web control within an UpdatePanel causes a postback - such as a Button Web control being clicked - instead of a regular postback the UpdatePanel performs a partial page postback. A partial page postback asynchronously communicates with the web server and sends the page's form field values. On the server, the page is re-rendered but only the HTML content for the appropriate UpdatePanel regions are returned to the browser. These regions are then dynamically updated. All of this hard work is handled for us by the client- and server-side pieces of the ASP.NET AJAX Framework.

    Our jobs as page developers are simple: just add an UpdatePanel control to the page and all that magical AJAXy goodness happens automatically. But what happens if we need more control over the partial postback life-cycle? For example, imagine that we need to execute some client-side script after the partial page postback completes? Or what if we want to cancel the partial page postback if some condition is true? The good news is that such custom functionality is available. We can create client-side event handlers that execute in response to certain events during the life-cycle of a partial page postback.

    The partial page postback is managed on the client-side by the PageRequestManager object. Whenever a partial page postback is initiated, the PageRequestManager object performs the following client-side actions:

    1. The initializeRequest event is raised - this is the first event raised during the partial postback life-cycle and affords us an opportunity to determine the HTML element that triggered the postback and cancel the postback, if needed.
    2. The beginRequest event is raised - this event is raised just before the request is sent to the server. The UpdateProgress control uses this event to displayed it's output.
    3. The request is sent to the server and the page is re-rendered there.
    4. The pageLoading event is raised when the server returns its response.
    5. The pageLoaded event is raised. This event is raised whenever the content on the page is refreshed, be it via a full page postback or a partial page postback.
    6. The endRequest event is raised, signalling completion of the partial page postback lifecycle.
    Keep in mind that these are client-side events. These events are being raised on the user's web browser. We can tap into these events by writing JavaScript that wires an event handler to one of these events.

    "Viewing" the Events Raised During the Partial Page Postback Life-cycle


    To better understand the stages of the partial page postback life-cycle, I've created a very demo with a Button in an UpdatePanel. When this Button is clicked, a partial page postback begins. I've also added client-side script that displays a message on screen as each of these events fires. Here's a boiled down version of this page's declarative markup:

    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>

    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
       <ContentTemplate>
          <asp:Button ID="PartialPostbackButton" runat="server" Text="Perform a Partial Postback" />
       </ContentTemplate>
    </asp:UpdatePanel>

    <asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1">
       <ProgressTemplate>
          <span style="color:Red;font-size:larger;">PERFORMING POSTBACK... THIS WILL TAKE FIVE SECONDS....</span>
       </ProgressTemplate>
    </asp:UpdateProgress>

    <div id="logOutput"></div>

    There are four key elements in the declarative markup:

    • The ScriptManager control. As discussed in previous installments of this article series, the ScriptManager is the "engine" that is needed in every AJAX-enabled web page.
    • The UpdatePanel control. This UpdatePanel includes a solitary Button control (PartialPostbackButton) that, when clicked, performs a partial page postback. I also have created a server-side event handler for this Button control that executes the code Thread.Sleep(5000), putting the thread to sleep for five seconds. This adds an artificial delay to the page so as to better illustrate what PageRequestManager object events fire before the request to the server and afterwards.
    • The UpdateProgress control. Displays a message during the five second delay on the server.
    • A <div> element with id logOutput. We will add JavaScript in a moment that logs messages to this element during execution of the various PageRequestManager event handlers.
    In addition to this markup, the demo page also includes the following JavaScript. (Note: when adding JavaScript that utilizes the ASP.NET AJAX Framework you can either add it directly within the ASP.NET page or as an external script file. This demo has the JavaScript content directly in the page. When adding script directly to the page it is vital that it appears after the ScriptManager control.)

    <script type="text/javascript">
       // Create the event handlers for PageRequestManager
       var prm = Sys.WebForms.PageRequestManager.getInstance();

       prm.add_initializeRequest(PageRequestManager_initializeRequest);
       prm.add_beginRequest(PageRequestManager_beginRequest);
       prm.add_pageLoading(PageRequestManager_pageLoading);
       prm.add_pageLoaded(PageRequestManager_pageLoaded);
       prm.add_endRequest(PageRequestManager_endRequest);

       function PageRequestManager_initializeRequest(sender, args) {
          logEvent("initializeRequest");
       }

       function PageRequestManager_beginRequest(sender, args) {
          logEvent("beginRequest");
       }

       function PageRequestManager_pageLoading(sender, args) {
          logEvent("pageLoading");
       }

       function PageRequestManager_pageLoaded(sender, args) {
          logEvent("pageLoaded");
       }

       function PageRequestManager_endRequest(sender, args) {
          logEvent("endRequest");
       }

       var count = 1;
       function logEvent(msg) {
          var logOutput = document.getElementById('logOutput');
          var rightNow = new Date();
          logOutput.innerHTML += '(' + count + ') ' + msg + ' (' + rightNow.toTimeString() + ')<br />';
          count++;
       }
    </script>

    The first line of code gets an instance of the PageRequestManager object. Next, the five PageRequestManager object events are wired up to five event handlers. Each of the five event handlers call the logEvent function, passing in a message to display. The logEvent function updates the logOutput <div>'s innerHTML, appending the message and current time.

    The three screenshots below show this demo in action. The first screenshot shows the page when it is first loaded. Note that the log output already contains one entry for the pageLoaded event. As noted earlier, the PageRequestManager object's pageLoaded event is raised whenever the page's contents have been refreshed whether we are dealing with a full page postback (such as when the page is first visited or when a control outside of an UpdatePanel causes a postback) or a partial page postback.

    The pageLoaded event handler is raised on every page load, whether its from a partial page postback or a full page postback.

    The second screenshot shows the page after the "Perform a Partial Postback" button has been clicked but before the server returns with its response. Note that the UpdateProgress control is showing its message (the text in red). Also, two new client-side event handlers have fired: initializeRequest and beginRequest.

    A partial page postback has started. The initializeRequest and beginRequest events have been raised.

    When the response is returned from the web server the remaining PageRequestManager object events fire: pageLoading, pageLoaded, and endRequest. Here you see that the response has returned from the server: the UpdateProgress control is no longer displayed and the event log lists the pageLoading, pageLoaded, and endRequest events. Notice that the pageLoading event was raised five seconds after beginRequest. This is because the server-side code that executes when the "Perform a Partial Postback" button is clicked sleeps for five seconds.

    The response has been returned from the server and the remaining events have fired.

    Aborting and Canceling Partial Page Postbacks


    The PageRequestManager object's initializeRequest event offers page developers an opportunity to cancel the postback, if needed. Furthermore, the PageRequestManager object includes a function that, when executed, aborts all partial page postbacks, both those that are in progress and those that are queued up. To illustrate aborting and canceling postbacks, I created a demo similar to the one we just examined. In addition to the Button control, I added a Label in the UpdatePanel that displays the time the UpdatePanel was updated. Outside of the UpdatePanel I added two controls used for demoing the abort and cancel features:
    • A CheckBox control named CancelThisPostback that, if checked, causes the partial page postback to be canceled, and
    • A button that, when clicked, aborts all outstanding postbacks.
    The page contains JavaScript similar to the previous example, as well. I've updated the client-side PageRequestManager_initializeRequest event handler, however, to cancel the partial page postback if the CancelThisPostback checkbox is checked:

    function PageRequestManager_initializeRequest(sender, args) {
             
       logEvent("initializeRequest");
       
       // See if we need to cancel this postback
       var cb = document.getElementById('<%=CancelThisPostback.ClientID%>');
       if (cb.checked) {
          // Cancel this postback request
          args.set_cancel(true);

          logEvent("Postback canceled");
       }
    }

    If the checkbox CancelThisPostback is checked the partial page postback is canceled by calling args.set_cancel(true); and a message is added to the log indicating that the postback was canceled. To test out this functionality, visit the page and click the "Perform a Partial Postback" button. As before, the page progresses through the various steps and the output is displayed in the client-side event handler log. Also, the time in the UpdatePanel is updated to the current time. Now, check the "Cancel this postback" checkbox and click the "Perform a Partial Postback" button. This time no partial page postback occurs.

    The following screenshot shows the output of the page when the "Cancel this postback" checkbox is checked. Note that the client-side event handler log has just three entries:

    • pageLoaded - this was displayed when the page was first loaded
    • initializeRequest - this was displayed when the "Perform a Partial Postback" button was clicked, thereby starting the partial postback life-cycle
    • Postback canceled - the postback was canceled.

    The partial page postback was canceled.

    This approach allows you to cancel the current partial page postback from the initializeRequest event handler. The ASP.NET AJAX Framework also allows you to abort all outstanding partial page postback requests. To accomplish this call the PageRequestManager object's abortPostBack() function. To demo using this functionality, I created the following client-side function, which is executed whenever the "Abort Outstanding Partial Page Postbacks" button is clicked.

    function AbortAllPostbacks() {
       var prm = Sys.WebForms.PageRequestManager.getInstance();
       prm.abortPostBack();
       
       logEvent("Partial page postbacks aborted");
    }

    To test this functionality, visit the demo page and click the "Perform a Partial Postback" button (with the "Cancel this postback" checkbox unchecked). This will start the partial page postback life-cycle. After the UpdateProgress output appears, click the "Abort Outstanding Partial Page Postbacks." This will abort the current partial page postback and immediately raise its endRequest event. The following screenshot shows the client-side event handler log when the "Abort Outstanding Partial Page Postbacks" button is clicked during a partial page postback. As you can see, the partial page postback started normally as its initializeRequest and beginRequest events were raised, but during the processing on the server the postback was aborted. This caused the endRequest event to be raised immediately.

    The ongoing partial page postback was aborted.

    Scrolling the Browser Window to a Particular HTML Element When the Partial Page Postback Completes


    I was recently working with a colleague who was using AJAX in a database search page. Essentially, users would enter various filtering criteria into TextBox controls, click a "Show Results" button, and the results would be displayed in a sortable and pageable GridView beneath the TextBox controls. The TextBoxes and GridView were both in an UpdatePanel.

    The page was laid out such that the "Show Results" button was at the bottom of the browser screen for users with low screen resolutions. After typing in search values into the TextBox controls and clicking the "Show Results" button, the GridView would be populated beneath the "Show Results" button, but these users would not see the results because they were "beneath the fold." In short, they needed to scroll down to see the results. But because AJAX provides such a smooth user experience, the users didn't realize that the page had been updated. There was no "flash" of the screen or other cue that their action - clicking the "Show Results" button - had done anything because the actual output was displayed further down on the page.

    The solution was to automatically scroll the user's browser to a particular HTML element situated directly above the output. This scrolling needed to occur whenever the partial page postback concluded.

    The browser's window object includes a scrollTo(x, y) method that will scroll to a particular (x,y) coordinate. With a little bit of script it's possible to determine the (x,y) coordinate of an HTML element. We found a script created by Eric Pascarello that packaged up this functionality into a JavaScript function named ScrollToElement(element). We then called this method passing in the HTML element to scroll to in the endRequest event handler.

    function PageRequestManager_endRequest(sender, args) {
       // Scroll to the specified HTML element
       var scrollTo = document.getElementById('scrollHere');
       ScrollToElement(scrollTo);
    }

    The scrollHere passed into the getElementById(id) function references a <div> element on the page located above the category drop-down list.

    Check out the demos available for download at the end of this article to see this functionality in action. The two screenshots below provide a glimpse at its behavior. The first screenshot shows the page when it is first viewed. At the bottom of the fold is a drop-down list where the user can select a category. Once they've selected a category and clicked the "Display Matching Products" button a GridView is displayed beneath the drop-down list that lists those products that belong to the selected category.

    By default, after clicking the "Display Matching Products" button the user's browser window would stay fixed in its current location. A user would have to manually scroll down to see the results and, if by chance the "Display Matching Products" button was already at the bottom of their browser window they might not realize that the report the requested was available further down on the screen.

    With the script added to this page, the user's browser is automatically scrolled to show the results when the partial page postback completes.

    Happy Programming!

  • By Scott Mitchell


    Attachments:


  • Download the Demo Code Used in this Article

    A Multipart Series on ASP.NET AJAX
    Over the past several years web developers have started using JavaScript to make asynchronous postbacks to the web server that only transmit and receive the necessary data; these techniques are commonly referred to as AJAX. Microsoft has released a free AJAX framework for ASP.NET developers named Microsoft ASP.NET AJAX. This article series examines using Microsoft's ASP.NET AJAX framework to build responsive user interfaces.

  • AJAX Basics and Getting Started with Microsoft's ASP.NET AJAX Framework - examines AJAX basics and looks at installing Microsoft ASP.NET AJAX; includes a demo of the UpdatePanel control.
  • Using the UpdatePanel - provides more in-depth and real-world examples of using the UpdatePanel.
  • Providing Visual Feedback with the UpdateProgress Control - shows how to use the UpdateProgress control to display visual feedback to the user when a partial page postback is in progress.
  • Performing Client Actions in Response to Partial Page Postbacks - learn how to execute client-side script in response to events raised by the partial page postback life-cycle.
  • Using the Timer Control - see how to asynchronously update a portion of the screen every n milliseconds.
  • Enabling Bookmarking and the Browser's Back Button - learn how to add history points to an AJAX-enabled web page so that your visitors can use their browsers' Back and Forward buttons and bookmarks.
  • Retrieving Server-Side Data Using Web Services - call Web Services from an ASP.NET AJAX application with a sprinkle of JavaScript.
  • A Look at JSON Serialization - explore the serialization format used by the ASP.NET AJAX Framework when calling Web Services from client-side script.
  • Triggering Full Page Postbacks From An UpdatePanel - learn how to override an UpdatePanel's default behavior and trigger a full page postback.
  • Refreshing An UpdatePanel With JavaScript - see how to refresh the contents of an UpdatePanel via JavaScript.
  • Rebinding Client-Side Events After a Partial Page Postback - discover how to automatically rebind client-side event handlers to HTML elements in an UpdatePanel after a partial page postback.
  • (Subscribe to this Article Series! )



  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article