ptg 1704 CHAPTER 38 Using Server-Side ASP.NET AJAX ApplicationLoadEventArgs Passed to the Application.load event handler. Supports the following properties: . components—The array of components created since the last time the Application.load event was raised. . isPartialLoad—Indicates whether the page is executing in the context of an asyn- chronous postback. EndRequestEventArgs Passed to the PageRequestManager.endRequest event handler. Supports the following properties: . dataItems—The data items registered with the ScriptManager.RegisterDataItem() method. . error—The error, if any, that occurred during the asynchronous postback. . errorHandled—Enables you to suppress the error. . response—The response associated with the asynchronous postback. NOTE You can detect whether a page is executing within the context on an asynchronous post- back within client code by using the PageRequestManager.isInAsyncPostBack property. The page in Listing 38.12 illustrates how you can take advantage of these event properties. The page contains two UpdatePanel controls. During an asynchronous call, the border of the active UpdatePanel turns the color orange. When the asynchronous call completes, the border of the updated UpdatePanel turns green. NOTE Later in this chapter, you learn how to use the UpdateProgress control to display an UpdatePanel’s pr og r es s . Th e me th o d de sc r ib e d in t h is sec t io n o f h a nd l in g c l ie n t events directly is useful when you want to display a custom progress indicator. LISTING 38.12 UpdatePanelCustomProgress.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <script runat=”server”> protected void btnSubmit_Click(object sender, EventArgs e) { System.Threading.Thread.Sleep(2000); // sleep 2 seconds From the Library of Wow! eBook ptg 1705 Using the UpdatePanel Control 38 } </script> <html xmlns=”http://www.w3.org/1999/xhtml”> <head runat=”server”> <title>UpdatePanelCustomProgress</title> <style type=”text/css”> .normal { width:300px; padding:10px; margin:10px; border: solid 4px black; } .updating { width:300px; padding:10px; margin:10px; border: solid 4px orange; } .updated { width:300px; padding:10px; margin:10px; border: solid 4px green; } </style> </head> <body> <form id=”form1” runat=”server”> <asp:ScriptManager ID=”ScriptManager1” runat=”server” /> <div id=”panelContainer”> <asp:UpdatePanel id=”up1” UpdateMode=”Conditional” runat=”server”> <ContentTemplate> <%= DateTime.Now.ToString(“T”) %> <asp:Button id=”btnSubmit1” Text=”Submit 1” OnClick=”btnSubmit_Click” Runat=”server” /> From the Library of Wow! eBook ptg 1706 CHAPTER 38 Using Server-Side ASP.NET AJAX </ContentTemplate> </asp:UpdatePanel> <asp:UpdatePanel id=”up2” UpdateMode=”Conditional” runat=”server”> <ContentTemplate> <%= DateTime.Now.ToString(“T”) %> <asp:Button id=”btnSubmit2” Text=”Submit 2” OnClick=”btnSubmit_Click” Runat=”server” /> </ContentTemplate> </asp:UpdatePanel> </div> </form> <script type=”text/javascript”> var prm = Sys.WebForms.PageRequestManager.getInstance(); prm.add_beginRequest(prm_beginRequest); prm.add_pageLoaded(prm_pageLoaded); function prm_beginRequest(sender, args) { var container = args.get_postBackElement().parentNode; container.className = ‘updating’; } function prm_pageLoaded(sender, args) { var panelsCreated = args.get_panelsCreated(); for (var k=0;k<panelsCreated.length;k++) panelsCreated[k].className = ‘normal’; var panelsUpdated = args.get_panelsUpdated(); for (var k=0;k<panelsUpdated.length;k++) panelsUpdated[k].className = ‘updated’; } </script> </body> </html> When the page in Listing 38.12 first loads in your browser, the PageRequestManager pageLoaded event is raised and the prm_pageLoaded event handler executes. This event handler assigns a default CSS class (named normal) to each of the UpdatePanel controls in From the Library of Wow! eBook ptg 1707 Using the UpdatePanel Control 38 the page. The list of UpdatePanels is retrieved from the PageLoadedEventArgs.panelsCreated property. If you click the first button, the border around the first button turns orange until the asynchronous postback completes and the border turns green. The same thing happens when you click the second button. When you click a button, the PageRequestManager beginRequest event is raised and the border around the button turns orange. After the response is returned from the server, the PageRequestManager pageLoaded event is raised and the border around the button turns green. The list of updated UpdatePanels is retrieved from the PageLoadedEventArgs.updated property. What happens if you click both buttons in rapid succession? In that case, you are attempt- ing to perform two simultaneous asynchronous postbacks. Unfortunately, the UpdatePanel does not support multiple simultaneous asynchronous postbacks. By default, the last post- back performed will abort all previous postbacks. Canceling the Current Asynchronous Postback As you learned in the previous section, you can perform at most one asynchronous post- back in a page at a time. By default, the last postback wins. If you initiate a new postback while a previous postback is being processed, the previous postback is aborted. If you want to reverse this logic, and give precedence to the first postback over future postbacks, you can cancel every postback that occurs after the first postback until the first postback completes. The page in Listing 38.13 illustrates how to cancel an asynchronous postback in the event handler for the PageRequestManager.initializeRequest event (see Figure 38.10). FIGURE 38.10 Canceling an asynchronous postback. From the Library of Wow! eBook ptg 1708 CHAPTER 38 Using Server-Side ASP.NET AJAX LISTING 38.13 UpdatePanelCancel.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <script runat=”server”> protected void btnSubmit_Click(object sender, EventArgs e) { System.Threading.Thread.Sleep(3000); // sleep 3 seconds } </script> <html xmlns=”http://www.w3.org/1999/xhtml”> <head runat=”server”> <title>UpdatePanel Cancel</title> </head> <body> <form id=”form1” runat=”server”> <asp:ScriptManager ID=”ScriptManager1” runat=”server” /> <asp:UpdatePanel ID=”up1” UpdateMode=”Conditional” runat=”server”> <ContentTemplate> <%= DateTime.Now.ToString(“T”) %> <asp:Button id=”btnSubmit1” Text=”Submit 1” OnClick=”btnSubmit_Click” Runat=”server”/> </ContentTemplate> </asp:UpdatePanel> <asp:UpdatePanel ID=”up2” UpdateMode=”Conditional” runat=”server”> <ContentTemplate> <%= DateTime.Now.ToString(“T”) %> <asp:Button id=”btnSubmit2” Text=”Submit 2” OnClick=”btnSubmit_Click” Runat=”server” /> </ContentTemplate> </asp:UpdatePanel> </form> <script type=”text/javascript”> From the Library of Wow! eBook ptg 1709 Using the UpdatePanel Control 38 var prm = Sys.WebForms.PageRequestManager.getInstance(); prm.add_initializeRequest( prm_initializeRequest ); function prm_initializeRequest(sender, args) { if (prm.get_isInAsyncPostBack()) { alert(‘Still Processing First Request’); args.set_cancel(true); } } </script> </body> </html> Using similar logic, you can always give precedence to one UpdatePanel over another. Listing 38.14 contains client-script that always gives precedence to the btnSubmit1 button over any other button that causes an asynchronous postback in the page. (The entire page is included in the source code on the book’s website). LISTING 38.14 UpdatePanelPrecedence.aspx <script type=”text/javascript”> var prm = Sys.WebForms.PageRequestManager.getInstance(); prm.add_initializeRequest( prm_initializeRequest ); var prevPostBackElementId; function prm_initializeRequest(sender, args) { if (prm.get_isInAsyncPostBack()) { if (prevPostBackElementId == ‘btnSubmit1’) { alert(‘Still Processing btnSubmit1 Request’); args.set_cancel(true); } } prevPostBackElementId = args.get_postBackElement().id; } </script> From the Library of Wow! eBook ptg 1710 CHAPTER 38 Using Server-Side ASP.NET AJAX If you click the second button (btnSubmit2) immediately after clicking the first button (btnSubmit1), the second asynchronous postback is canceled. Aborting the Previous Asynchronous Postback You can explicitly abort a previous asynchronous postback by using the PageRequestManager abortPostBack() method. Explicitly aborting a postback is useful when you want to associate a Cancel button with an asynchronous postback (see Figure 38.11). For example, the page in Listing 38.15 contains two buttons. The first button retrieves your fortune. The oracle, however, is slow. It takes 3 seconds for the oracle to deliver a new fortune. If you want to cancel the new fortune during these 3 seconds, you can click the Cancel button. LISTING 38.15 UpdatePanelAbort.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <script runat=”server”> protected void btnGetFortune_Click(object sender, EventArgs e) { System.Threading.Thread.Sleep(3000); // wait 3 seconds lblFortune.Text = String.Format(“At {0:T}, the oracle says: “, DateTime.Now); Random rnd = new Random(); switch (rnd.Next(4)) FIGURE 38.11 Aborting an asynchronous postback with a Cancel button. From the Library of Wow! eBook ptg 1711 Using the UpdatePanel Control 38 { case 0: lblFortune.Text += “You’re doomed!”; break; case 1: lblFortune.Text += “Good luck is around the corner.”; break; case 2: lblFortune.Text += “Don’t leave home.”; break; case 3: lblFortune.Text += “Buy stock today.”; break; } } </script> <html xmlns=”http://www.w3.org/1999/xhtml”> <head runat=”server”> <title>UpdatePanel Abort</title> </head> <body> <form id=”form1” runat=”server”> <div> <asp:ScriptManager ID=”ScriptManager1” runat=”server” /> <asp:UpdatePanel ID=”up1” runat=”server”> <ContentTemplate> <asp:Button id=”btnGetFortune” Text=”Get Fortune” OnClick=”btnGetFortune_Click” Runat=”server” /> <asp:Button id=”btnCancel” Text=”Cancel” Enabled=”false” Runat=”server” /> <br /> <asp:Label ID=”lblFortune” runat=”server” /> </ContentTemplate> </asp:UpdatePanel> </div> </form> <script type=”text/javascript”> From the Library of Wow! eBook ptg 1712 CHAPTER 38 Using Server-Side ASP.NET AJAX var prm = Sys.WebForms.PageRequestManager.getInstance(); prm.add_initializeRequest(prm_initializeRequest); function prm_initializeRequest(sender, args) { if (args.get_postBackElement().id == ‘btnCancel’) { prm.abortPostBack(); alert(“Fortune Aborted!”); } else { $get(‘btnCancel’).disabled = false; } } </script> </body> </html> Passing Additional Information During an Asynchronous Postback You can pass additional items from the web server to the web browser during an asynchro- nous postback. Passing additional items is useful when the area that you need to update on a page does not fall into a neat little rectangle. For example, you might want to update a page’s title or a page’s meta tags based on the results of an asynchronous query. The page in Listing 38.16 contains a DetailsView control that you can use to navigate the contents of the Movie database table. The DetailsView control is contained inside of an UpdatePanel control so that a postback does not happen when you navigate to a new movie. LISTING 38.16 UpdatePanelDataItem.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <script runat=”server”> protected void dtlMovie_DataBound(object sender, EventArgs e) { string movieTitle = (string)DataBinder.Eval(dtlMovie.DataItem, “Title”); if (sm1.IsInAsyncPostBack) { sm1.RegisterDataItem(Head1, movieTitle); } From the Library of Wow! eBook ptg 1713 Using the UpdatePanel Control 38 else { Head1.Title = movieTitle; hTitle.InnerHtml = movieTitle; } } </script> <html xmlns=”http://www.w3.org/1999/xhtml”> <head id=”Head1” runat=”server”> <title>UpdatePanel DataItem</title> </head> <body> <form id=”form1” runat=”server”> <div> <asp:ScriptManager id=”sm1” Runat=”server” /> <h1 id=”hTitle” runat=”server”></h1> <asp:UpdatePanel id=”upSearch” Runat=”server”> <ContentTemplate> <asp:DetailsView id=”dtlMovie” DataSourceID=”srcMovies” AllowPaging=”true” Runat=”server” OnDataBound=”dtlMovie_DataBound” /> </ContentTemplate> </asp:UpdatePanel> <asp:SqlDataSource id=”srcMovies” ConnectionString=’<%$ ConnectionStrings:con %>’ SelectCommand=”SELECT Id,Title,Director FROM Movie” Runat=”server” /> </div> </form> <script type=”text/javascript”> From the Library of Wow! eBook . ptg 17 04 CHAPTER 38 Using Server-Side ASP. NET AJAX ApplicationLoadEventArgs Passed to the Application.load event handler. Supports the following properties: . components—The array of components. { width:300px; padding:10px; margin:10px; border: solid 4px black; } .updating { width:300px; padding:10px; margin:10px; border: solid 4px orange; } .updated { width:300px; padding:10px; margin:10px;. From the Library of Wow! eBook ptg 1706 CHAPTER 38 Using Server-Side ASP. NET AJAX </ContentTemplate> < /asp: UpdatePanel> < ;asp: UpdatePanel id=”up2” UpdateMode=”Conditional” runat=”server”>