It’s important to remember that a partial
postback is just that: A
postback.
The UpdatePanel’s way of abstracting AJAX functionality behind standard WebForm methodology provides us with flexibility and familiarity. However, this also means that using an UpdatePanel requires careful attention to the
ASP.NET Page Life Cycle.
In this post, I’d like to point out a few of the problems I’ve seen developers running into and what you can keep in mind to avoid them:
- Page events still fire during partial postbacks.
- UpdatePanel events fire, even when not updating.
- Control event handlers fire after Load events.
Page events still fire during partial postbacks
One of the most common things that new ASP.NET AJAX developers overlook is that
all of the Page’s life cycle events (Page_Load, Page_PreRender, etc)
do execute during every partial postback. During a partial postback, the Page’s control tree is fully reinstantiated and every single control runs through its life cycle events. If that’s not taken into account, it’s very easy to run into mysterious difficulties.
Page.IsPostBack is
true during partial postbacks, making it easy to avoid this pitfall. However, it’s a problem that surfaces at least daily on the ASP.NET forums, so it bears mentioning.
Additionally, ScriptManager.IsInAsyncPostBack is
true during partial postbacks only. This property can be used to further distinguish what type of request is being processed.
UpdatePanel events fire on each and every request
Using the UpdatePanel’s life cycle events (Init, Load, PreRender, and Unload) can be a great way to partition your code and enables you to use __doPostBack() to trigger the UpdatePanel from JavaScript. However, it is crucial to understand that these events will execute on every page load, postback, and partial postback.
Even if you’re using UpdatePanels with conditional UpdateModes and some of those UpdatePanels aren’t being visibly updated in a given partial postback,
all of them will be recreated on the server and execute any life cycle event handlers you’ve wired up for them.
Typically, this means that should wrap your code in an !IsPostBack or !IsInAsyncPostBack conditional if you don’t want it to execute on every request. However, one slightly more tricky situation is when you want to execute code only if a particular UpdatePanel is targeted for a refresh. To accomplish that, you can check the __EVENTTARGET:
protected void UpdatePanel1_PreRender(object sender, EventArgs e)
{
// This code will only be executed if the partial postback
// was raised by a __doPostBack('UpdatePanel1', '')
if (Request["__EVENTTARGET"] == UpdatePanel1.ClientID)
{
// Insert magic here.
}
}
Control events are raised after Load events
One of my readers recently ran into what is probably the second most common page life cycle problem I’ve seen.
Basically, he had an UpdatePanel and Button interacting with each other to create a simple poll. The UpdatePanel’s Load event rendered poll results from a database table, while Button_Click let users submit their poll votes to the database.
Can you see the problem?
If you read the subheading above, it’s probably obvious. Button_Click was running
after UpdatePanel_Load, giving his users the impression that their votes were not being counted since the display didn’t change when they voted.
The fix? Instead of rendering the poll in UpdatePanel_Load, he needed to render it in the PreRender event instead, because UpdatePanel_PreRender fires after Button_Click.
It sounds simple when spelled out, but it’s a mistake we’ve probably all made at one time or another. The extra layer of complexity that AJAX brings to the table only makes it easier to accidentally forget about subtle page life cycle issues.