Are you making these 3 common ASP.NET AJAX mistakes?
AJAX, ASP.NET By Dave Ward on October 24th, 2007
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.
Similar posts
What do you think? Your comments are welcomed.
I appreciate all of your comments, questions, and other feedback, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums. If you post there and then contact me with a link to the post, I'll try to take a look at it for you.
If you're replying to an existing comment, please use the threading feature. To do this, click the "Reply to this comment" link underneath the comment you're replying to.
Trackbacks
- October 25th Links: ASP.NET, ASP.NET AJAX, Visual Studio, Silverlight and IIS 7.0 - ScottGu's Blog
- Are you making these 3 common ASP.NET AJAX mistakes? - Joe On ASP.NET
- Web Application Development with Microsoft Technologies » Monthly AJAX.NET, ASP.NET, Silverlight Links.- October 2007
- Are you making these 3 common ASP.NET AJAX mistakes? « DOT NET
- Geek Daily » Blog Archive » Are you making these 3 common ASP.NET AJAX mistakes?
- October 25th Links: ASP.NET, ASP.NET AJAX, Visual Studio, Silverlight and IIS 7.0 « .NET Framework tips
- 3 veel voorkomende fouten met Asp.Net Ajax - Jowen

Comments
That’s why we’re moving towards abandoning the postback model ;)
Indeed. I’m really excited about seeing where the MVC framework goes.
Though that will just change problems… since the MVC framework doesn’t have postback and viewstate, a lot of problems these things cause will come back…
For example, request validation. Let say I have a dropdown with 3 options, a lot of people don’t realise anyone can type javascript in the bar (or something similar) and add a 4th option and click submit… By default, the current model stops these things, but the MVC framework, at first glance, won’t have stuff like that (this is just an example, so if this particular one isn’t true, the general idea still is).
Frameworks are just compromises… fixing one problem creates another :) I for one, much prefer the the postback model with MVP pattern.
That’s definitely true.
There will never be a panacea that replaces deep understanding of your chosen framework, be it RoR, LAMP, ASP.NET, or whatever else comes along next.
Not a moment too soon, if you ask me!
Very good read! This will solve a lot of my problems before I even have them. Thanks Dave!
Thank you for summarizing this. Even though this ought to be common sense, we all know about common sense, it’s uncommon. I have bookmarked this to read it every once so often, just to refresh and be reminded
rams
Another very nice asp.net ajax article. Good Job! You and Matt Berseth (www.mattberseth.com) need to get together and do a blog where both of you post on it. You guys have such similar content that you guys could really drive some traffic!
Thanks, Justin.
I don’t think I could keep up with Matt! I have no idea how he manages to crank out so many good posts so quickly.
Along similar lines,
doing a data bind after the page Load event changes the names of the bound controls. This had me stumped for a while when I was receiving error messages on a postback. The cause: I had forgotten to check for !IsPostback before doing the databind.
I usually call my table/grid-loading function at the end of my button click events that modify said tables/grids. Is PreRender the preferred method simply to reduce code duplication, or is there something more fundamental I’m missing?
I typically do the same with doing things in load, and then modifying them in the click event handler. I avoid most of the code duplication by putting the databinding or whatever code in a private method that both the load and click handlers call.
Lately I’ve been trying to use only page load (and not prerender, init, etc.) because it simplifies things and I don’t have to know about all the details of the page lifecycle. I could use more of the lifecycle hooks, but it tends to get really messy and hard to follow.
Certainly, there are several solutions to the problem. I think if you have something that’s working well for you, you should stick with it.
That said, I find PreRender more elegant in that situation. Why call the function in two places, when you can call it once and achieve the same result?
When someone comes back to work on that code in a year, they will appreciate the simplicity of a single code path to your DataBind routine.
I definitely think having multiple options is great. There’s never one “best” way to do something that applies to every situation. In this case I have nothing against using prerender for the databinding.
Where I have been burned with page lifecycle events is when I had to fix a page and several controls that were all tightly coupled together. There was something like a preinit on the page, then a init on the control, then a init on the other control (and the inits had to run in the right order), a load on the page, and a prerender on the page. And if everything didn’t run in just the right order, it would crash.
A mandatory read for any ASP.NET developer : THE ASP.NET PAGE LIFE CYCLE. This and the ViewState are the most important (in my opinion) to understand the way ASP.NET works.
I had trouble with the Request.Params[”__EVENTTARGET”] in my C# code.
The request seemed to store the information with the $ charater between the masterpage and control panel, update panel etc.
Whereas the UpdateBtn.ClientID data had _ as the separator. So they did not compare right. I eneded up putting the code in the PreRender evenet and checking the ScriptManager.IsInAsyncPostBack to do the work.
- Anil
I’m disheartened that this article even needed writing. An understanding of the Page Lifecycle is one of the most fundamental tools that a .NET developer should have.
And I would suggest that it is accessible articles like this that will help newcomers to ASP.NET to understand just that. Especially if they are teaching themselves, as a lot of people do.
@Dave - please keep up your excellent work.
One problem i am having is that when page refreshed via F5
The gridview rowcommand event is not refiring
It is working fine previously when the application were not ajaxify.But after ajaxifying the application this behavior come into existence
That is normal behavior. The reason that happens is because there isn’t a formal request for your browser to re-send, like there is with a traditional postback.
You can use something like UpdateHistory to work around that problem.
I have a User Control (UCSecurePage) that I had intended to be able to placed on every page within a site that I needed to be role based. I placed my code in the Page_Load of UCSecurePage to see if the user was logged in and had rights. The only way that I could consistently have the code run within the UCSecurePage was to create a public method and call that public method from the pages that contained UCSecurePage. This works, but doesn’t “feel” right. Is there a better way to accomplish this?
Assuming you left AutoEventWireup on, the Page_Load of a user control should run automatically. What trouble were you having, before you added the public method?
Aside from that, it sounds like you might be reinventing the wheel. Forms authentication provides a lot of built-in flexibility for doing things like that.
Dave,
The Page_Load of the user control was running automatically, but I wanted to be able to drop the UCSecurePage onto a webform and have it’s Page_Load run before the Page_Load of the webform.
You can use Page_PreLoad to run that right before Page_Load. If all you’re doing is redirecting users without proper security you could do it very early, in Page_PreInit.
Makes sense. So I would have to keep the public method within UCSecurePage and I could call that method from the Page_PreLoad or Page_PreInit of the webform.
You could move that code into Page_PreLoad or Page_PreInit in the user control itself, and eliminate the publicly exposed method completely.
Really? I’ve tried putting the code into the Page_PreInit method of the UC and the Page_Load of the webform still ran first. I hadn’t tried the Page_PreLoad of the UC. I am curios if my having AJAX on the form is somehow conflicting.
That shouldn’t be the case. You might want to step through that in the debugger and see what’s happening. The user control event life cycle is basically the same as the page’s, without as many events, and runs in parallel.
Dave,
I have stepped through the debugger and have verified it hits the Page_Load of the webform first. I’ll keep playing around with it.
I found the solution to my problem by reading this article… http://www.tgreer.com/aspnet_html_04.html I added a protected override void OnInit of the user control and that method calls my VerifyUser method first before all webform Page_Load events fire.
I think the if should be:
if (Request[”__EVENTTARGET”] == UpdatePanel1.UniqueID)
They can generally be used interchangeably, when triggering a postback. Calling __doPostBack(’< %= UpdatePanel1.ClientID %>‘, ”) or __doPostBack(’< %= UpdatePanel1.UniqueID %>‘, ”) will both trigger the same partial postbacks (assuming you have an UpdatePanel1).
However, if you use the UniqueID with getElementById or $get, you’ll get a null reference. So, I’ve found it best to be consistent and always use the ClientID.
Rather interesting problem: “you want to execute code only if a particular UpdatePanel is targeted for a refresh”.
Panel update is an effect of business logic operations that were “triggered” by user action, but not the cause. What for we need to know what panel is updating?
Also I think that using Request[”__EVENTTARGET”] in PreRender will create a bottleneck on a big page. We already have event-based notification system and IPostBackEventHandler interfact. What for we need to filter event targets manually?
If you’re handling events like UpdatePanel_Load and don’t check something to filter which postbacks you act on, that’s going to cause more performance loss than the actual act of filtering.
Think of it like using !IsPostBack in Page_Load. This is essentially the same thing.
But it’s not the same. I use !IsPostBack to initialize the page, then user makes an action and I update only required parts of the page. The rest will be restored from viewstate. And it doesn’t matter if it is async postback or not.
The only thing that I can optimize with this is the size of “dynamic” part of control tree. But it’s like splitting hairs. Reflection manipulations in AjaxControlToolkit controls and data access layer issues can cause much more perfomance loss.
How would you propose to implement that functionality differently that would be significantly better? Keep in mind that this is intended to handle a __doPostBack() event raised against no control other than the UpdatePanel itself.