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.

Summary

  • Page_Load executes during every partial postback, same as regular postbacks.
  • Use IsPostBack and IsInAsyncPostBack to avoid accidental execution of Page_Load code during partial postbacks.
  • In conjunction with __doPostBack, __EVENTTARGET may be used to limit UpdatePanel life cycle event execution to only the targeted panel.
  • Control events, such as Click and SelectedIndexChanged, fire after Load events.
  • By using PreRender instead of Load, you can allow control events to be handled before your code executes.

In conclusion, it is not possible to overstate how important it is for you to understand the ASP.NET page life cycle if you intend to develop ASP.NET AJAX pages. I guarantee you that an hour spent deeply familiarizing yourself with it today will save you orders of magnitude more time in the future.

Have I missed page life cycle issues that you’ve run into when working with ASP.NET AJAX? Leave a comment with the problems that you’ve run into, so that we can learn from your experience.