Are you making these 3 common ASP.NET AJAX mistakes?
AJAX, ASP.NET By Dave Ward. Updated April 21, 2008
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?
I appreciate all of your comments, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums or Stack Overflow instead.
If you're replying to another comment, use the threading feature by clicking "Reply to this comment" before submitting your own.
19 Mentions Elsewhere
- 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
- Are you making these 3 common ASP.NET AJAX mistakes? « Jwalin’s Weblog
- 用__doPostBack在client端更新UpdatePanel | Horn Network
- Sıfırdan AJAX öğrenebileceğiniz 20 kaynak
- Are you making these 3 common ASP.NET AJAX mistakes? « Evil Science
- The Seven Sins of DotNetNuke Module Developers | TechBubble
- October 25th Links: ASP.NET, ASP.NET AJAX, Visual Studio, Silverlight and IIS 7.0 | OOP - Object Oriented Programing
- Interactive Logic » Blog Archive » Easily refresh an UpdatePanel, using JavaScript [Encosia]
- Are you making these 3 common ASP.NET AJAX mistakes? : MS-Joe
- How to Improve ASP.NET UpdatePanel Performance « Er. alokpandey's Blog
- SharePoint Google Geospacial Dashboard Solution – Lessons Learned « Sue Hernandez's Blog
- Eric Barnard. Iterations. » Blog Archive » ASP.NET Webforms Page Life Cycle–The Basics
- Updatepanel things to remember « Sansknowledge's Blog



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.
You will note that the subject of this article is about the Ajax UpdatePanel. Using Ajax, without knowing the fundamentals of ASP.NET, is rather like trying to run before you can walk.
Actually, AJAX itself is relatively simple. It’s the ASP.NET abstraction of AJAX that makes things so convoluted and easy to do improperly. It also makes things a major pain if you ever decide to move away from .NET to an alternative like NGINX with Python or even Node.js as you will basically have to rewrite the entire codebase. Sticking with quality javascript frameworks like JQuery for client-side and AJAX functionality makes everything more portable and clean in my opinion. While you lose a little bit of the “magic” that comes with ASP server controls, you also lose most of the complexity and limitations while gaining the power of mature, portable javascript frameworks. If you ever do decide to move to or away from .NET you can probably re-use 70-80% of the codebase as well. I know this article was posted 5 years ago, but it is just as relevant now considering that people are still having the same problems with ASP.
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.
I completely admit that I did not understand the page lifecycle, and never realized how important it is until messing with some ajax. I have done a couple things before and used a check for Page.IsPostBack to control things before. Did not know the order of lifecycle events though. So thank you for the quick intro in my ignorance.
That said, I used your code sample to check to see which updatepanel is requesting postback. I found that my updatepanels are not the __EVENTTARGET, but the trigger, so:
but:
and really, ClientID would not equal the Request either as Request["__EVENTTARGET"] returns this: “ctl00$Content$DropDownList”
and my DropDownList.ClientID returns this:
“ctl00_Content_DropDownList”
So reading the comments here, I see UniqueID is supposed to be interchangeable. I replaced ClientID with UniqueID and I get correct returns.
Any reason why my code would be causing the differences here? Note: I do the check for this in the Page_Load event. Although I did try in the UpdatePanel’s PreRender event and the same data was being returned.
I’ve run into that myself, and to be perfectly honest I’m not completely clear on why the $ delimited UniqueID comes back sometimes, but not usually. I think it has to do with controls being inside ITemplate containers, like content pages, GridView templates, etc.
If you find a definitive answer, let me know. I’ll add a note to that section of the post.
It’s been a while, but I re-read this and I think the answer is that, at least in my particular case, the control was in a child page. If you have a control in a stand alone page, I believe both ClientID and UniqueID return the same values, but when that page is nested in a MasterPage, the control names gain the extra text of the master page and the ContentPlaceHolder name. And I believe UniqueID places ‘_’ characters between the identifiers while ClientID places ‘$’ in those same spots and the EVENTTARGET happens to return the same name as the UniqueID.
Could be wrong, but that’s what I think is happening.
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.
Thank you so much for your explanation on the ordering of control events vs. page events!
I had the exact issue you described with the controls contained within the update panel not reflecting my server-side changes.
Putting the requisite code in the update panels prerender event worked perfectly!
The common mistakes are:
1. Working with the postback model for everything, including things that can be done on the client.
2. Using UpdatePanels. The Asp.Net AJAX library is pretty good, but for most things, UpdatePanels should be avoided.
It is like a soul to heart as ajax for asp.net
Good work, thank you!
Being little conscious, we can avoid the above mentioned problems. Most of the times troubles are generated by the poor page design using updatepanels. For example, use of multiple updatepanels unnecessarily. And update in one updatepanel may lead to update of all others, which we could avoid by use of Conditioal Update Mode.
Such problems can be avoided by good understanding of update panels.And lets never forget the big part ajax has contributed in web development!
I have any update panel set to conditional updateMode with a trigger against a dropdown out side the panel and childrenastriggers as false. I load user controls dynamically on this panel.The user control has one drop down list with autopost back set to true.
On selecting value in the user control drop down my script manager isAsynPostback still comes true. Should’nt this is false as i have childrenastriggers set to false?
That’s not the behavior I would expect either.
i have a different kind of problem. When my application redirects to another page and later when i click back button on my browser all the data on my previous page gets cleared which was on the update panel. Where exactly am i missing. Please guide
ASP.NET AJAX has a feature to provide browser history support. Check out ScriptManager.AddHistoryPoint for an entry point into that functionality.
But as i go on adding the history points for each control on the page one after another, the addhistorypoint had added the point for last selected control only. So when i select multiple controls, the add history point restores the state only for the last selected control.
In the paging scenario, you’ll need to somehow store those fields (e.g. session state or database) and use history points for each page.
Great insight. I admit , that I was making the same mistakes :(. But now I will not …. :)
Very nice article, just what I was looking for!
Thank you so much! That bit about using __EVENTTARGET to determine which UpdatePanel triggered the partial page postback solved a nagging problem in my app!
Hi Dave,
how can i display the static content initially on the page and later the update panel content. Its like the user should be able to see atleast something on the screen and later the other dynamic fields comes from db.
for eg:
Top of the panel
//in between the update panel which contains gridview
Bottom of the panel
my requirement is to display the static content first as soon as the page load happens and later the update panel content…..as if the gridview takes long time to process then user has to wait for the same duration stairing the white screen….
i have used
but it executes later only but all the content are displaying at the same time only……
Plz suggest me the proper events or something with which i can fulfill the requirement using the ajax & update panel.
The order of events doesn’t have any bearing on client-side rendering. You can’t implement deferred loading by tweaking that. Once all the server-side events have fired, the total of all that rendering gets sent to the browser in one chunk.
If it’s read-only content, you can use a technique like this to get the deferred loading effect: http://encosia.com/2008/02/05/boost-aspnet-performance-with-deferred-content-loading/
Actually I don’t like to post comments on websites, but your PreRender suggestion is amazing. Thank you very very much.
I have run in to a problem on which i have spent hours.
I have two divs with an update panel. and I want to toggle the display on a button clicks. The event is fired and the code the executed but my update panel wont update. But “onselectedindexchanged” event for my dropdown works fine.
I know my question sound silly. Any suggestion is highly appreciated
Make sure those buttons are set as async triggers of the UpdatePanel.
Thank You Dave for your reply. I figured out that the ASP validator in one of the div tags is causing the problem. Btw, your article on 3 common ajax mistakes is awesome and very informative. Also I have another question. Do Jquery validations work in the update panel?
I’ve got a couple of posts here covering how to use jQuery Validation with WebForms, starting here: http://encosia.com/2009/11/04/using-jquery-validation-with-asp-net-webforms/
Thank You. This is exactly what I am looking for. You are the best.
In my situation I solved the problem with the following code placed at the oninit and prerender. My situation is that I use master page and a number of custom controls some of which have update panels. On one page I have 3 update panels, and by using this code at oninit and prerender I only fire the update panels I want.
bool isAsynch = ((ScriptManager)this.Page.Master.FindControl(“MasterScriptManager”)).IsInAsyncPostBack;
if (HttpContext.Current.Request["__EVENTTARGET"] != null)
{
if (!HttpContext.Current.Request["__EVENTTARGET"].Contains(“NAME OF MY CONTROL THAT FIRED THE UPDATE”) && isAsynch)
{
return;
}
}
For instance if I have a dropdownlist where the change event fires the update, I simply have to check for the name of the control and either allow the processing to continue or stop immediately.
Correction… I do not place this on the onit event, only on the prerender. All of my custom controls that have an update panel either cache their drop down list values, and the actual data binding events that happen in the update panels are called from pre-render. By using the code I posted I only pre-render the controls I want to update. By the way this works as well for controls without the update panels that are on this same page obviously. THe only tricky part is if you are intending on repurposing the controls you may run into an issue.
I don’t mean to be a jerk, this post is great and useful, but from a design perspective it doesn’t make too much sense to me why an ajax call would cause asp.net to fully reinstantiated the Page’s control tree and every single control run through its life cycle events (other than providing a familiar – but architecturally illogical api)??
Now that you’ve told me I can live with it, and fair enough you have the Page.isPostBack & ScriptManager.IsInAsyncPostBack set to true… it’s all good.
But consider this scenario:
-) I have a user control that gets automatically generated on page load, many times (I only want them generated once).
-) On each user-control I want ajax to send some user-control data (collected in a form) back to the server (so it can be written to a DB). You can probably already see, that since user-controls were added dynamically, I have to store them somewhere in view state and retrieve them for display with evert ajax update-panel call, since otherwise the page loads-up blank without these controls.
-) This in my opinion is a lot of cost for using the abstraction advantage of the update-panel. Isn’t ajax all about not having to re-create / re-load all the elements other than the ones that are necessary?
-) … and finally let’s assume that all my user control needs to do is just to store the few data-items from a form on the user-control to the db, and no manipulation of HTML on the client is really necessary. In that case the update-panel is just a huuuge overkill… much better to simply write some Jquery AJAX code to get the data-items on client side and send them to the server, no need then to worry about saving and re-loading ddynamically generate user controls!
Any feedback would be welcome, what do you guys think?
You have no idea how much you helped me!
I made almost every mistake you metioned there…
hi,
i have a “protected void Page_Unload(object sender, EventArgs e)” and i want fire it when user close or redirect to other pages, but i have updatepanel too that is updated with a timer every 3s and it is firing my “protected void Page_Unload(object sender, EventArgs e)”, i use “if (!IsPostBack)” but it didnot do what i want.
how can i do that.
sorry for my bad english, thx.
i have a question in update panel.
if i have 3 textbox and 3 dropdownlist.
i want when i was selected a dropdownlist1 value then textbox1 will visible. same as dropdown2 and dropdown3 will visible textbox 2 & 3. when i select a value of dropdownlist1 then textbox1 will visible. But when i was selected other dropdownlist value textbox of that dropdownlist is visible but others are invisible.
So, can i know how i use this updatepanel in my code.
HI,
I have an asp.net form contains ajax update panel. I am redirecting this page to another page . There i am trying to access the first page controls using request.form. But i am not getting the values. But for the controls outside update panel , i am getting values. Any body can assist on this ?
Thanks in Advance
Nabeel P H