When an ASP.NET page performs a postback to the server, there is often a pause followed by a flash of the browser screen as content returned from the server is rendered. During this pause, the user cannot interact with the application. The disruption becomes even more pronounced if the server needs extra time to process user input or retrieve data from a remote source.
To run an ASP.NET Ajax web site, you need:
A web server running IIS 5 or later (for local development, the Visual Studio 2005 Web Server can be used instead)
ASP.NET 2.0, which can be downloaded from http://msdn.microsoft.com/netframework/downloads/updates/default.aspx
ASP.NET Ajax, which can be downloaded from http://ajax.asp.net/default.aspx?tabid=47&subtabid=471
Any text editor can help you develop an ASP.NET Ajax site, but we recommend you download and install the free Visual Web Developer 2005 IDE, available at http://msdn.microsoft.com/vstudio/express/vwd/download/.
Some of the samples in this Short Cut require SQL Server Express, the free version of SQL Server that can be downloaded as part of Visual Web Developer Express or from http://msdn.microsoft.com/vstudio/express/sql/download/. We use the SQL Server sample database, AdventureWorks, for which download and installation instructions can be found at http://msdn2.microsoft.com/en-us/library/ms310325.aspx.
On the client side, IE6 or later, Firefox 1.5 or later, Opera 9 or later or Safari 2 or later is necessary.
The UpdatePanel
control is one of
several ASP.NET Ajax features you can use to improve the experience of
your users by hiding much of the interaction between browser and
server.
A well-designed AJAX application provides visual clues to the user
to indicate that communication is taking place in the background.
Typically, this is done with animation, such as the familiar hourglass
or spinning graphic most browsers display during navigations and
postbacks. Later, you'll see how UpdatePanel
also enables this scenario.
For the majority of user inputs, the whole page does not usually need to be refreshed, and, while a user's action in the browser may require a return to the server to get updated data, typically only part of the page is affected.
A search page, for example, typically includes a navigation menu, a title, a search form, and a search results list. When a user enters search criteria and clicks the Search button, the search results list must be updated, but not the navigation menu or search form. Similarly, when a user navigates between search results, the search results region of the page needs to be updated, but not the other elements.
The ASP.NET Ajax UpdatePanel control lets you restrict updates to
particular areas of a page. Using the control, you can even come up with
new ways to navigate search results that are simply not possible with
regular postbacks. A results list, for example, can be programmed to grow
as the user scrolls down through its contents. You can also display
detailed descriptions of individual search items on demand by fetching
them only when requested, an operation that would be more expensive if you
had to download all of the descriptions with the initial request response.
This last scenario can be implemented entirely with UpdatePanel
, as we'll show in later sections of
this Short Cut (See the section "Creating a
Search Page with a Pop-up Details Preview").
Let's begin by learning how to add the UpdatePanel
control to a web application and how
to make use of its properties.
Once you've installed ASP.NET Ajax, the easiest way to set up your application is to create a new web site with Visual Studio 2005 or Visual Web Developer using one of the ASP.NET Ajax site templates. To do this, open Visual Studio 2005 and select File → New Web Site, as shown in Figure 1.
Next, in the My Templates section of the Templates panel of the New Web Site dialog, shown in Figure 2, select ASP.NET Ajax Web Site. Choose your file system as the location for the web site by selecting File System from the Location drop-down list. Also, select VB.NET or C# from the Language drop-down list, whichever you prefer (we use C# in the examples). Click OK once you've made your selections.
Once you've completed these steps, Visual Studio creates a new web site (AJAXEnabledWebSite1) with the folders, files, and resources you need to get started, as shown in Figure 3.
In the following paragraphs, we explain each of these elements and show you the manual steps you need to take to do what the site creation wizard does automatically. If you need to ASP.NET Ajax-enable an existing site, the operations can't be done automatically.
The application's Web.config file in
particular must include the following settings (here, we describe only
the settings that are necessary for UpdatePanel
, not other settings needed by
other parts of ASP.NET Ajax). Open Web.config and
add the following markup to the system.web
section:
<system.web> <pages> <controls> <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </controls> </pages> <compilation debug="false"> <assemblies> <add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </assemblies> </compilation> <httpHandlers> <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/> </httpHandlers> <httpModules> <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </httpModules> </system.web>
Finally, any page that needs to use an UpdatePanel
must contain a ScriptManager
control and a server form (see
the section "The
ScriptManager Control Dependency").
The general form of an UpdatePanel
control is shown in the following
pseudocode:
<asp:UpdatePanel EnableViewState="true|false" UpdateMode="Always|Conditional" RenderMode="Block|Inline" ChildrenAsTriggers="true|false"> <Triggers> <asp:AsyncPostBackTrigger ControlID="someID" EventName="someEventName" /> <asp:PostBackTrigger ControlID="someID" /> </Triggers> <ContentTemplate> <!-- HTML and ASP.NET content goes here --> </ContentTemplate> </asp:UpdatePanel>
We explain the properties of the UpdatePanel
tag in the following
sections.
The UpdatePanel
control
specifies regions within a page that can be refreshed in isolation. It
can contain a Triggers
collection
(which we'll discuss shortly), and needs a ContentTemplate
property. The ContentTemplate
property defines the area of
the page that can be updated asynchronously from the browser, as shown
in the following:
<asp:UpdatePanel runat="server" ID="updatePanel"> <ContentTemplate> <!-- HTML and ASP.NET content goes here --> </ContentTemplate> </asp:UpdatePanel>
The runat="server"
attribute,
as ASP.NET developers know, tells the parser that this is a server
control, while the ID
attribute is
necessary for Visual Studio to switch to design view and is very useful
for easily referencing the control from the code.
The contents of the template can appear on the page as if the
UpdatePanel
control weren't around
it, without disrupting the page's layout (see the section "The
RenderMode Attribute"). This means you can add an UpdatePanel
control to an existing page
without altering the appearance of the page. We recommend you give it a
meaningful ID, as you would for any server control.
When a postback is initiated from the browser, it normally causes
the page to refresh completely. The UpdatePanel
control necessitates that the
postback be handled asynchronously from JavaScript running in the web
browser, and avoids the usual interruption. Instead of sending the
entire page's content back to the client, it sends back only the HTML
rendered within the areas defined by a ContentTemplate
property. This new markup is
accompanied by the updated viewstate data, header, and scripts. Then the
ASP.NET Ajax JavaScript code running in the browser dynamically replaces
the target areas of the page directly in the browser's DOM (Document
Object Model).
UpdatePanel
controls can be
added to existing pages without the need to redesign an application or
write custom JavaScript. Multiple UpdatePanel
controls can be used in a single
page, which allows you to isolate updates to the page area that need to
change to reflect users' actions. Event handlers do not need to be
modified to account for the use of the UpdatePanel
control. During the asynchronous
server-side postback, the viewstate information is restored to the
controls on the page, so controls within the UpdatePanel
can rely on the property values of
controls anywhere else on the page.
The UpdatePanel
control
requires that a ScriptManager
control
also be present on the page. If no ScriptManager
control is present, UpdatePanel
throws an exception and the page
does not finish executing. As part of this dependency, the ScriptManager
must appear before the UpdatePanel
in the page. We recommend placing
it at the top of the form before any other controls. The ScriptManager
control coordinates the
distribution of ASP.NET Ajax JavaScript to the browser along with other
JavaScript registered by controls on the page. Multiple UpdatePanel
controls can be on a page, but
there can be only a single ScriptManager
. Here's the simplest ScriptManager
tag you can write to enable
UpdatePanel
controls on a
page:
<asp:ScriptManager EnablePartialRendering="true" runat="server" ID="manager" />
The EnablePartialRendering
property of the ScriptManager
control
indicates that additional JavaScript needs to be included on the page to
change how postbacks are handled.
If you use Master Pages with your applications, we recommend you
put the ScriptManager
control in
the Master Page. In some Master Page scenarios, you may need to add
settings such as script or service references from the contents page.
This can be done by adding a ScriptManagerProxy
control to the content
page and adding the references to that control.
This updated version traps the postback on the client and performs
the operation asynchronously. There is no user interruption or browser
flash. The ScriptManager
is also
signaled to intercept key phases of the page's lifecycle during the
asynchronous postback. The controls within the UpdatePanel
control do not need to be aware
that they are in an UpdatePanel
in
most situations, and behave no differently than they otherwise would.
The ScriptManager
control isolates
the updated viewstate data for the page and the rendering from all
UpdatePanel
control contents that
need to be refreshed. This data is the return result of the asynchronous
postback. The fact that the ScriptManager
and UpdatePanel
work together to do partial
rendering updates on the client is completely transparent to the
controls on the page.
In many cases, you do not need to refresh the contents of an
UpdatePanel
control on every postback
to the server. The UpdatePanel
control provides an UpdateMode
property you can use control when the refresh should occur. UpdateMode
can be set to Always
or Conditional
. By default, the contents of the
UpdatePanel
are always refreshed. If
UpdateMode
is set to Conditional
, the UpdatePanel
relies on its Triggers
collection and on the position of the
control that triggered the asynchronous postback to determine when the
contents are updated. If the control responsible for the postback is
inside the panel or is referenced by one of the triggers, the panel is
always refreshed. The Triggers
and
ContentTemplate
elements are the only
elements allowed as direct children of the UpdatePanel
:
<asp:UpdatePanel UpdateMode="Conditional" > <Triggers> <!--Trigger elements go here --> </Triggers> <ContentTemplate> <!-- HTML and ASP.NET content goes here --> </ContentTemplate> </asp:UpdatePanel>
Individual event triggers can specify events from other controls
whose changes should be monitored. When the event is fired, the
rendering is captured from the UpdatePanel
and sent back from the server to
the browser.
AsyncPostBackTrigger
forces a
conditional UpdatePanel
to be
updated each time a specific event on a given control is fired. The
ControlID
attribute points to the
control that triggers the event, and EventName
is the name of the event to
monitor. For example, the following trigger forces an update of the
panel whenever the Button1
button
is clicked:
<asp:ControlEventTrigger ControlID="Button1" EventName="Click" />
By default, any postback event of any control that is inside of
an UpdatePanel
control will trigger
an asynchronous update for that panel. Using an AsyncPostBackTrigger
is only necessary if
the panel must be updated when an event on a control that is
not in the UpdatePanel
control is fired.
Whereas AsyncPostBackTrigger allows a control outside of an UpdatePanel to trigger an asynchronous update, the PostBackTrigger does the exact opposite: it allows a control inside of an UpdatePanel control (which would by default trigger an asynchronous postback) to cause a regular synchronous postback. You do not have to specify a specific event: all postback events on the control will cause regular postbacks.
When the page is rendered, an UpdatePanel
control renders as either a
SPAN
or a DIV
element within the page. The ID
of the UpdatePanel
is included on this element and is
later used by the JavaScript as the location where content is updated.
If you don't specify an ID
, one is
generated for you, but we recommend you specify a meaningful ID
, at least to make debugging easier. The
RenderMode
property tells the
UpdatePanel
which element to use as
the container for the markup that is refreshed. The default RenderMode
value is Block
, which means a DIV
HTML element is used. When the property is
set to Inline
, the SPAN
element is used. Block
should be used when the contents of the
panel can take up all the space on the current line, and Inline
should be used when the contents of the
panel should not disrupt the flow of the text. It should also be noted
that, as XHTML tags, SPAN
and
DIV
are not allowed in all contexts
because the former is an inline element and the latter is a block
element, which may affect your choice for RenderMode
.
The following example shows an UpdatePanel
control that displays as a
SPAN
:
<asp:UpdatePanel RenderMode="Inline"> <ContentTemplate> <!-- HTML and ASP.NET content goes here --> </ContentTemplate> </asp:UpdatePanel>
When interacting with the server using navigation or postbacks, the browser typically displays some animation, such as a flapping Windows flag, that tells the user it's working and that he should wait for the server to respond (See Figure 4.)
When you use AJAX technologies, communication with the server is
done with XmlHttp
, which doesn't
trigger any animation on the browser. UpdatePanel
is no exception to that; if the
server does not respond instantaneously, the user may think that his
action did not have any consequence. He may react by frantically
clicking the same button over and over, which will only increase the
strain on the server. This is clearly not a good user experience.
A basic UI design principle is that the user should get immediate feedback for any action. In the case of an asynchronous operation that may take a long time to complete, such as a server interaction, this immediate feedback can be a simple wait message, but web applications usually add an animated GIF next to the text message.
For operations that are likely to take an especially long time to complete, the application may even provide a Cancel button. Note that you can cancel only the update to the page, and it is likely that the request will reach the server anyway and side effects will occur. For example, canceling a save operation won't necessarily prevent the data from being saved but will prevent the feedback from coming back and updating the page. This should be seen as a way to retake control of the application and not as an actual cancellation of an operation that may have already reached the server.
ASP.NET Ajax introduces an UpdateProgress
control, which makes it easy to
add progress indications to an ASP.NET 2.0 page. The UpdateProgress
control is
templated, which means that the look of your
progress notification is completely customizable. The control with its
design-time smart tag is shown in Figure 5.
In the Visual Studio designer, a default template can be created by clicking in the control design surface, as shown in Figure 6.
The Abort Request button is an input type="button" element with a click client-side event that aborts the async postback: <input type="button" onclick="abortPostback" value="Abort request"/>
The abortPostback function in this example is a global function that you can define this way:
function abortPostback(e) { var prm = Sys.WebForms.PageRequestManager.getInstance(); if (prm.get_isInAsyncPostBack()) { prm.abortPostBack(); } }
The function gets the client-side instance of the page request
manager, which is the object that manages UpdatePanel
controls on the client-side. Then,
it asks this object if it is currently doing an asynchronous update and
aborts it if it's the case. We'll have more opportunities to explore
PageRequestManager
in the following
sections.
The UpdateProgress
control is
not visible on the page when it first loads in the browser, but whenever
an asynchronous postback takes place, it is automatically displayed
until the response comes back from the server or the request is
canceled. Figure 7 shows a
typical control.
The UpdateProgress
control is
not associated with a particular UpdatePanel
control by default and any
asynchronous update will trigger the appearance of the UpdateProgress
control for the duration of the
asynchronous postback. Even though the update is triggered by one
particular panel, it may affect more than one or even all of them.
However, in some scenarios, you may want to associate different UpdateProgress
controls to different triggers
on the page. This can be done by setting the AssociatedUpdatePanelID
property.
While it is good practice to give a visual indication
acknowledging the user's action as soon as possible, if the server
responds very fast to the asynchronous postback (typically under half
a second), the user may only see the progress indication for just a
split second. In those cases, it's better not to show the progress
indication at all because the operation seems to be instantaneous and
the flash of the progress would be an unnecessary distraction. This is
why by default, the UpdateProgress
control will only display after 500 milliseconds and only if the
server hasn't responded before that time. This delay can be customized
by setting the DisplayAfter
property on the UpdateProgress
control.
In the same way that ASP.NET validators can be configured to
only take space on the page when they are triggered, UpdateProgress
controls don't take space on
the page unless there is an ongoing asynchronous update. As it's the
case for validators, UpdateProgress
can be configured so that its space on the page is occupied (but
empty) even when there is no ongoing update. This is done by setting
the DynamicLayout
property to
false.
If a control is not inside an UpdatePanel
control and is not registered as a
trigger for an UpdatePanel
control,
it will trigger a regular ASP.NET 2.0 postback.
You may want to force a control (such as a button) to trigger an
asynchronous postback instead. You can do this by calling the RegisterAsyncPostBackControl
method on the
ScriptManager
control.
This method is also used by triggers under the hood.
One of the most common applications of UpdatePanel
is to update a specific part of
the page at regular intervals. While there is a cost to this in terms of
the application's scalability, such applications do exist and using
UpdatePanel
is a good way to work
around the disconnected nature of HTTP and replace information pushing
with polling.
ASP.NET Ajax introduces the TimerControl
, which makes this very easy to
set up. It is important to note that the actual ticking of the TimerControl
happens client-side, not
server-side. When added to a page, it creates a client-side timer that
triggers a postback on each tick.
While TimerControl
is not
absolutely tied to the UpdatePanel
control, it is especially useful when both are combined and the timer's
tick event is used as the trigger of an UpdatePanel
control. The postbacks then become
asynchronous and can be used to regularly update a specific part of the
page.
It is important to realize that the TimerControl
can be a big obstacle when it
comes to scaling your application. The number of users you anticipate
and the kinds of operations you execute during the tick event should be
carefully balanced against the interval you choose for the timer. The
interval should not be significantly smaller than the typical update
frequency of the data being displayed. For example, refreshing a list of
blog posts every second seems excessive; an interval of several minutes
is probably more appropriate. Conversely, a chat application would
typically update every few seconds, though we don't recommend you
develop a chat client using AJAX technologies.
The default interval of TimerControl
is 60 seconds, which should not
be too much of a strain on a typical application.
Example 1 shows how
you can use TimerControl
to update
the time on the page every five seconds.
Example 1. Using TimerControl with UpdatePanel to update the time on a page every five seconds
<%@ 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>Clock</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="SM1" />
<div>
<asp:TimerControl runat="server" ID="Time" Interval="5000" Enabled="true" />
<asp:UpdatePanel runat="server" ID="TimePanel">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Time" EventName="Tick" />
</Triggers>
<ContentTemplate>
<%= DateTime.Now.ToLongTimeString() %>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
In Example 1, the tick
event is used only as a trigger for the UpdatePanel
control, but it is an ordinary
server event despite the fact that the timing itself happens
client-side. It is of course perfectly possible to handle this tick
event server-side and do some work from there.
During an asynchronous postback, the page is in a state that is
close to that of a regular postback. For instance, Page.IsPostback
is true during an asynchronous
postback.
It can be useful to determine if the postback is a regular
postback or an asynchronous one. This can be done by inspecting ScriptManager
's IsInAsyncPostBack
property.
Sometimes, it is even necessary to determine if a specific
UpdatePanel
control will be updated
or not. The IsInPartialRendering
property of UpdatePanel
does exactly
that, but it's impossible for the framework to determine that
information reliably before Render. For that reason, this property
always returns false until Render and is not
suitable for consumption by page developers. It's really only
there for component developers and should only be trusted during
Render.
Finally, the specific control that triggered the partial update can be identified by using the AsyncPostBackSourceElementID property of ScriptManager, which returns the unique ID of the control on the page. A reference to that control can then be retrieved using Page.FindControl.