Académique Documents
Professionnel Documents
Culture Documents
aspx
MSDN Magazine > Issues > 2007 > June > Wicked Code: UpdatePanel Tips and Tricks
Wicked Code
Contents
Update Highlighting
Canceling UpdatePanel Updates
Multiple UpdatePanels
Updates without UpdatePanels
Web Service != SOAP and XML
For better or for worse, the UpdatePanel control is the darling of the ASP.NET AJAX community. I say "for
better" because UpdatePanel makes partial-page rendering shockingly easy and "for worse" because its
simplicity and ease-of-use come at the cost of efficiency and, ironically, bandwidth.
While UpdatePanel brings AJAX magic to ordinary Web pages, it doesn’t bring the efficiency we normally
associate with AJAX. Did you know, for example, that when an UpdatePanel control performs an asynchronous
AJAX callback to the server to update its content, the request contains everything a conventional ASP.NET
postback contains, including view state? Most developers assume that AJAX eliminates view state. That’s not
the case, though, with UpdatePanel’s brand of AJAX.
If you’re going to use an UpdatePanel control, you need to know what you’re getting in to. In many cases, from
a performance point of view, an application is better off not using UpdatePanel and instead using
asynchronous calls to WebMethods or page methods. Doing so can reduce the volume of data traveling over
the wire by an order of magnitude or more. However, it’s also a fundamental shift where the UI updates need
to be handled explicitly by the developer with JavaScript in the page.
In addition, ASP.NET AJAX discussion forums are already filled with questions about customizing UpdatePanel.
Many of these questions are easily answered once you know about PageRequestManager, the JavaScript class
in the Microsoft® AJAX Library that provides the client-side support for UpdatePanels.
Now that ASP.NET AJAX has shipped, I’d like to examine UpdatePanel more closely—taking a close look at
how you can customize it, optimize it, and even live without it. And that’s exactly what this column is all about.
Current Issue
Update Highlighting
Sometimes you can’t help but feel sorry for the developers at Microsoft. If they don’t do their job well enough,
they get pounded by the public. However, they sometimes also get slammed if they do their job too well. For
example, I recently got e-mail from a customer complaining that the ASP.NET AJAX UpdatePanel works a little
too well.
UpdatePanel makes it extremely easy to take all that flashing and flickering that occurs when an ASP.NET page
posts back to the server and turn it into smooth, flicker-free updates. UpdatePanel works its magic by
converting postbacks into asynchronous callbacks (XML-HTTP requests) and using JavaScript on the client to
refresh the part of the page encapsulated by the UpdatePanel control. The flashing and flickering goes away
because the browser doesn’t repaint the page as it does during a postback.
The customer’s complaint was that users were sometimes not noticing that part of the page had been updated
with new content. His question was simple: can the folks on the ASP.NET AJAX team make UpdatePanel flicker
just a little so important updates won’t be missed?
The bad news is that the ASP.NET AJAX team probably isn’t interested in making UpdatePanels flicker. After all,
getting rid of the flicker is why UpdatePanel was invented in the first place. The good news is that you can Browse All MSDN Magazines
work a little AJAX magic in the browser to draw attention to updated UpdatePanels. The secret is the
Sys.WebForms.PageRequestManager class in the Microsoft AJAX Library—the library of JavaScript classes that
comprise the client half of ASP.NET AJAX. PageRequestManager manages the asynchronous callbacks
launched by UpdatePanel. It’s also responsible for updating the content inside an UpdatePanel when an
asynchronous callback completes.
PageRequestManager fires events in the browser before and after an update occurs. You can hook these
events in JavaScript and run code that draws a user’s attention to the updated content. The key event is named
pageLoaded. This event fires each time the page loads in the browser (it’s analogous to Page_Load in
ASP.NET). It also fires each time an asynchronous callback launched on behalf of an UpdatePanel control
completes and the content inside that UpdatePanel is updated. You can register a JavaScript handler for the
pageLoaded event with two lines of code (which can be combined into one):
The first line acquires a reference to the page’s PageRequestManager object. The second registers a JavaScript
function named pageLoaded as a handler for pageLoaded events.
When called, a pageLoaded event handler receives an argument of type Sys.WebForms.PageLoadedEventArgs,
which is another class in the Microsoft AJAX Library. PageLoadedEventArgs contains a get_panelsUpdated
method that you can call to enumerate all the UpdatePanels, if any, whose content was just updated. By
1 of 7 11/5/2010 7:32 PM
Wicked Code: UpdatePanel Tips and Tricks http://msdn.microsoft.com/en-us/magazine/cc163413.aspx
default, an UpdatePanel is nothing more than a DIV on the client-side so you can use JavaScript to flash the
DIV, highlight it, or do whatever you want to do to draw a user’s attention to it.
The code listed in Figure 1 shows one way to use pageLoaded events to perform update highlighting. Each
time an update occurs, this JavaScript flashes the Document Object Model (DOM) elements representing
updated UpdatePanels by making them appear and disappear three times in quick succession. The flashing is
performed by a helper function named flashPanels, which takes a flash count as an input parameter.
<script type=”text/javascript”>
if (panels.length > 0)
{
_panels = new Array(panels.length);
flashPanels(3);
}
}
function flashPanels(count)
{
_count = (count << 1) + 1;
window.setTimeout(toggleVisibility, 50);
}
function toggleVisibility()
{
for (i=0; i < _panels.length; i++)
_panels[i].set_visible(!_panels[i].get_visible());
if (--_count > 0)
window.setTimeout(toggleVisibility, 50);
}
</script>
Note how an updated UpdatePanel’s visibility is toggled on and off to create a flashing effect. Rather than
interacting with DOM elements directly, the code wraps the DOM elements representing the UpdatePanels
with Sys.UI.Control objects. Then it uses Sys.UI.Control’s set_visible and get_visible methods to toggle the
visibility:
_panels[i].set_visible(!_panels[i].get_visible());
Sys.UI.Control is a JavaScript class found in the Microsoft AJAX Library—specifically, in MicrosoftAjax.js. The
benefit to toggling visibility in this manner is that this is browser-independent. This works equally well in every
browser that supports ASP.NET AJAX (which is virtually all modern browsers). JavaScript code that interacts
directly with the browser DOM, on the other hand, would have to be tweaked to work in different browser
types.
2 of 7 11/5/2010 7:32 PM
Wicked Code: UpdatePanel Tips and Tricks http://msdn.microsoft.com/en-us/magazine/cc163413.aspx
<script type=”text/javascript”>
In this sample, before a callback executes, an intializeRequest handler pops up a confirmation box asking the
user whether the update should proceed. Clicking Cancel in the confirmation box passes true to set_cancel,
which stops the callback in its tracks. In real life, you probably aren’t interested in prompting the user for
confirmation before allowing an update to proceed, but it might be useful to have the ability to cancel an
update based on conditions elsewhere in the application.
Incidentally, it’s also possible to cancel asynchronous callbacks after they’ve been executed but before they’ve
completed. PageRequestManager provides an abortPostBack method for doing this; it also provides a
get_isInAsyncPostBack method for determining whether an asynchronous callback is pending. These methods
are often used with UpdateProgress controls to present a cancellation UI.
Multiple UpdatePanels
A page can host several UpdatePanels. By default, when one UpdatePanel on a page updates, the other
UpdatePanels on the page also update. Sometimes that’s what you want, but more often than not, you don’t
need every UpdatePanel updating in response to other UpdatePanels.
You can be selective about which UpdatePanel instances update (and when) by setting the UpdateMode
property of each UpdatePanel control on the page to "Conditional." Then, when one UpdatePanel updates and
calls a server-side event handler, call UpdatePanel.Update on the other panels you want to update. This
reduces the load on the server by reducing the number of controls that render, and it reduces the volume of
data in the response because UpdatePanels that don’t update don’t add anything to the response.
3 of 7 11/5/2010 7:32 PM
Wicked Code: UpdatePanel Tips and Tricks http://msdn.microsoft.com/en-us/magazine/cc163413.aspx
Figure 3 City, State, and ZIP Code UI (Click the image for a larger view)
Here’s the problem. An UpdatePanel used this way improves the user experience, but it does little to reduce
the volume of data being passed over the wire. The UpdatePanel hardly reduces the load on the server,
either—up to the point that the controls inside the UpdatePanel render, the processing performed on the
server is almost identical to what happens during a full-blown postback. It has to be this way because one of
the benefits of the UpdatePanel control is that server-side event handlers like GetCityAndState work no
differently inside an asynchronous callback than they do in a traditional postback. That means controls on the
page have to be instantiated, they have to be initialized, they have to have access to view state, and so on.
Figure 4 demonstrates how to implement the same functionality without an UpdatePanel control. This time,
the Autofill button is wired to a bit of JavaScript that fires off an asynchronous XML-HTTP request to an ASMX
Web method named GetCityAndState. The call is placed through the JavaScript proxy named ZipCodeService,
which is generated by the service reference in the ScriptManager control. GetCityAndState takes a ZIP Code
string as input and returns a string array containing two items: the corresponding city and state. The
completion function onGetCityAndStateCompleted retrieves the items from the array and inserts them into the
city and state fields. Same result on the outside, but a very different way of going about it on the inside.
4 of 7 11/5/2010 7:32 PM
Wicked Code: UpdatePanel Tips and Tricks http://msdn.microsoft.com/en-us/magazine/cc163413.aspx
City:<br />
<asp:TextBox ID=”City” runat=”server” />
<br /><br />
State:<br />
<asp:DropDownList ID=”Region” runat=”server”>
<asp:ListItem Value=”AL”>Alabama</asp:ListItem>
<asp:ListItem Value=”AK”>Alaska</asp:ListItem>
<asp:ListItem Value=”AZ”>Arizona</asp:ListItem>
...
<asp:ListItem Value=”WV”>West Virginia</asp:ListItem>
<asp:ListItem Value=”WI”>Wisconsin</asp:ListItem>
<asp:ListItem Value=”WY”>Wyoming</asp:ListItem>
</asp:DropDownList>
<br /><br />
Zip Code:<br />
<asp:TextBox ID=”ZipCode” runat=”server” />
<asp:Button ID=”AutofillButton” Text=”Autofill”
OnClientClick=”autoFill(); return false;” runat=”server” />
<script type=”text/javascript”>
function autoFill()
{
var tb = new Sys.Preview.UI.TextBox ($get(‘ZipCode’));
var zip = tb.get_text();
if (zip.length == 5)
ZipCodeService.GetCityAndState (zip,
onGetCityAndStateCompleted);
}
function onGetCityAndStateCompleted(result)
{
if (result != null)
{
var tb = new Sys.Preview.UI.TextBox ($get(‘City’));
tb.set_text(result[0]);
var select =
new Sys.Preview.UI.Selector ($get(‘Region’));
select.set_selectedValue(result[1]);
}
}
</script>
Here’s how the ASMX Web method called through the JavaScript proxy is implemented:
[ScriptService]
public class ZipCodeService : System.Web.Services.WebService
{
[WebMethod]
public string[] GetCityAndState(string zip)
{
...
}
}
This is a standard Web method in every respect except for the fact that the class to which it belongs is
attributed ScriptService instead of WebService. ScriptService is synonymous with WebService, but it carries the
added meaning that the Web service’s WebMethods are callable from client-side script.
In addition to allowing conventional WebMethods to serve as targets for XML-HTTP requests, ASP.NET AJAX
also supports a special type of Web method known as the page method. Page methods are WebMethods
implemented in Web pages—that is, in ASPX files or codebehind files rather than in ASMX files. Page methods
allow developers to provide endpoints for XML-HTTP callbacks without building dedicated Web services.
Page methods must be public static methods and, like WebMethods, must be decorated with the WebMethod
attribute. (WebMethods and page methods can also be decorated with the ScriptMethod attribute, which
provides added control over what goes out over the wire.) On the client, page methods are called from
JavaScript through the special PageMethods proxy.
Unlike Web services, page methods do not require service references. However, you do have to enable page
methods by setting a ScriptManager control’s EnablePageMethods property to true, like so:
5 of 7 11/5/2010 7:32 PM
Wicked Code: UpdatePanel Tips and Tricks http://msdn.microsoft.com/en-us/magazine/cc163413.aspx
Under the hood, page methods offer the same efficiency as WebMethods. View state and other input is not
transmitted to the server when page methods are called. And since page methods are static, they can be called
without instantiating a page object. A call to a page method does not invoke the page lifecycle that is
triggered by conventional ASP.NET requests.
Request
{"zip":"98052"}
Response
HTTP/1.1 200 OK
Server: ASP.NET Development Server/8.0.0.0
Date: Fri, 29 Dec 2006 21:06:17 GMT
X-AspNet-Version: 2.0.50727
Cache-Control: private, max-age=0
Content-Type: application/json; charset=utf-8
Content-Length: 16
Connection: Close
{"REDMOND", "WA"}
JSON is an up-and-coming industry-standard serialization format. It’s also the native format employed by
ASP.NET AJAX. JSON serialization and deserialization support is provided on the client-side by the Microsoft
AJAX Library’s Sys.Serialization.JavaScriptSerializer class. On the server, support is provided by the
System.Web.Script.Serialization.JavaScriptSerializer class.
Not all types are JSON-compatible. JSON cannot, for example, handle objects with circular references. When
you need to return complex data types that aren’t JSON-compatible, you can actually use ASP.NET AJAX’s
ScriptMethod attribute to serialize return types into XML. This technique is also useful for methods that return
XML data, as demonstrated here:
[ScriptMethod (ResponseFormat=ResponseFormat.Xml)]
public XmlDocument GetData()
{
...
}
Alternatively, you can build and register custom JSON converters that allow types that aren’t normally
JSON-compatible to be serialized and deserialized. The ASP.NET AJAX January Futures CTP contains three
such converters: one for DataSets, one for DataTables, and one for DataRows.
6 of 7 11/5/2010 7:32 PM
Wicked Code: UpdatePanel Tips and Tricks http://msdn.microsoft.com/en-us/magazine/cc163413.aspx
Jeff Prosise is a contributing editor to MSDN Magazine and the author of several books, including
Programming Microsoft .NET (Microsoft Press, 2002). He’s also a cofounder of Wintellect
(www.wintellect.com), a software consulting and education firm that specializes in Microsoft .NET.
© 2010 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks | Privacy Statement | Site Feedback
7 of 7 11/5/2010 7:32 PM