The UpdatePanel
control is
certainly a very useful addition to the ASP.NET developer's arsenal, but
replacing postbacks with asynchronous callbacks has a few side effects
that can look strange if you don't fully understand how it really works.
In this section, we present some of these unexpected effects.
Most WebControls should work in an UpdatePanel
without modifications. Those
that register scripts, in particular instance initialization scripts,
though, may fail to work correctly. This is due to the fact that we're
running under severely different assumptions. With regular postbacks,
every user interaction basically throws away the old page and
rehydrates a new one from scratch: you get a new page, a new DOM, and
the scripts start from a vanilla state and are run again. With partial
updates, the page potentially lives forever. During an update, the new
script will run from a state that has been affected by those that ran
before it, during the GET request and during previous partial updates.
For that reason, it becomes essential that client-side objects dispose
of themselves and that the server can discover what scripts need to be
sent to the client again.
For those reasons, controls that want to work inside of an UpdatePanel need to follow a few rules, the main one being to start using ScriptManager registration methods instead of the ones ASP.NET 2.0 exposes on Page.ClientScript.
Eilon Lipton explains in great details how to write controls for UpdatePanel without necessarily having to take a hard dependency to ASP.NET Ajax in the following blog posts:
It is possible to nest UpdatePanel
controls, but this makes sense
only if the outermost panel has a conditional mode. Otherwise, any
update to the inner panel triggers the update of the outer panel, and
the results are as if there was only the outer panel.
Playing with the markup in Example 11 by changing the mode of each panel and observing the result when you load the page is probably the best way to get an intuitive feel for what's going on here. Try it.
Example 11. Nested UpdatePanels
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Nested UpdatePanels</title> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager runat="server" ID="SM1" /> <div> <asp:UpdatePanel runat="server" ID="OuterPanel" UpdateMode="Conditional"> <ContentTemplate> Outer panel updated at: <%= DateTime.Now.ToLongTimeString() %> <asp:Button runat="server" ID="PostOuterButton" Text="Post outer panel" /> <asp:UpdatePanel runat="server" ID="InnerPanel" UpdateMode="Conditional"> <ContentTemplate> Inner panel updated at: <%= DateTime.Now.ToLongTimeString() %> <asp:Button runat="server" ID="PostInnerButton" Text="Post inner panel" /> </ContentTemplate> </asp:UpdatePanel> </ContentTemplate> </asp:UpdatePanel> </div> </form> </body> </html>
Figure 18 shows the page that displays when you load Example 11 in a browser.
Figure 18. Nested UpdatePanel controls enable the developer to define multiple levels of update granularity for the same region of the page
During an asynchronous postback, the IsInPartialRendering
property of an UpdatePanel
control nested inside another
one is false if the parent panel is being refreshed. So the contents
of the inner panel are refreshed but only because
the outer panel is being refreshed, so this is reflected only by the
IsInPartialRendering
property of
the outer panel, not the inner one.
ASP.NET postbacks are designed to happen sequentially, because on every postback the whole page is torn down and recreated. When you replace ASP.NET postbacks with asynchronous callbacks that update only part of a page, there is always the possibility that several asynchronous calls could happen at the same time. This is OK if each part of the page maintains its own state, which is possible with client-side applications, but ASP.NET pages don't work this way; they manage state centrally in viewstate.
The viewstate of a page is a typical example of a state repository that is updated on every postback. The viewstate is essential to most ASP.NET applications. If several simultaneous calls were allowed by ASP.NET Ajax asynchronous postbacks, there would be no way to reliably predict the order in which each request would come back from the server. What version of the viewstate should replace the previous one? In theory, the new page states could be merged with the old ones. Unfortunately, this would be highly impractical. It is actually a lot simpler and a lot more stable to maintain this essential characteristic of the old postback model and keep things sequential. This is the choice that we made when developing ASP.NET Ajax.
Consequently, even if your page contains several parts that can update independently from a design perspective, updates still happen sequentially. This does not mean that a particular round-trip involves only one panel: any asynchronous postback can involve as many panels as need to be updated. What this means is that while an asynchronous postback is in progress, any other attempt to post back is ignored by default.
xml-script is a new declarative XML syntax introduced by the
ASP.NET Ajax Futures CTP client-side framework. It may be tempting to
include an xml-script block in an UpdatePanel
. This is not currently supported
because the ASP.NET Ajax team encourages page developers to choose
between the server-side approach (i.e., UpdatePanel
and ASP.NET Ajax-enabled
controls and extenders) and a fully client-side approach that uses
only xml-script and JavaScript.
When updating a region of the page, it is necessary to clean up the region that is being updated before you create the new HTML and initialize the new xml-script structures that may be associated with them. Because arbitrarily embedded xml-script is literal contents, as far as the server is concerned, it is very difficult to ensure these housekeeping operations are reliably performed.
.
It is sometimes desirable to programmatically force a
conditional UpdatePanel
to update,
without necessarily using a trigger to do it. This is easily done by
calling the Update
method on the
panel.
Similarly, it may be useful to block the update of a panel. This scenario is not currently supported.
File upload fields are very important form fields for many reasons. One of the reasons is that they access the remote user's filesystem. Because of this, there has to be very strict security restrictions, in particular with regard to scripting. For example, it is impossible to obtain the path or contents of the file from script.
During an asynchronous postback, the form is sent using script
and XmlHttp
instead of the built-in
posting logic of the browser. Therefore, it is impossible to reproduce
the posting of an upload field from script.
One way to handle file uploads in a partially updated page is to
isolate uploads outside all UpdatePanel
controls or in a completely
different page in a pop-up window or IFrame. In the case of an upload,
a regular postback occurs, and in a pop-up window, the main page is
not affected.