If you've been working with UpdatePanels in ASP.NET Ajax, I'm sure you appreciate how simple they make it to add Ajax behavior to almost any ASP.NET page. You can easily isolate portions of your page to update independently using asynchronous callbacks instead of refreshing the entire page with a standard post-back. In order to keep the programming model identical to that of a synchronous post-back page, however, the UpdatePanel-initiated request will run through your server-side page logic in its entirety, which is often doing more than needed to fulfill the request to update only the contents of the UpdatePanel that actually initiated the request (this is assuming you have set UpdateMode='Conditional').
If you have every tried to optimize your page logic to perform only the steps necessary to populate the contents of the UpdatePanel that issued the request, you may have run across the alluring attribute IsInPartialRendering available on the UpdatePanel class. Unfortunately this attribute is always false until deep into the rendering code (or so I've been told, I've never actually seen it get set to true myself) even if the UpdatePanel you are querying was the one to initiate the request. However, you can identify which UpdatePanel issued the async postback by querying the ScriptManager's AsyncPostBackSourceElementID property, which tells you the ID of the control that initiated the async postback, from which you can then infer the corresponding UpdatePanel. For example, if you had the following UpdatePanel defined:
<asp:UpdatePanel id="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Label ID="Label1" runat="server" Text="Panel Created" />
<asp:Button ID="Button1" runat="server" Text="Refresh Panel 1"/>
<ContentTemplate>
<asp:UpdatePanel>
you would know that it issued the async postback if AsyncPostBackSourceElementID of the ScriptManager was set to Button1. You could then implement your Page Load handler to set the text of the label in the panel only if it was a) not an async postback or b) it was an async postback initiated by this particular UpdatePanel:
protected void Page_Load(object sender, EventArgs e)
{
if (!ScriptManager1.IsInAsyncPostBack ||
ScriptManager1.AsyncPostBackSourceElementID == "Button1")
{
// Refresh panel 1 data
Label1.Text = "Panel refreshed at " + DateTime.Now.ToString();
}
}
In this case we're not really saving much in the way of server-side processing, but if we had to query a database or invoke a Web service to populate the label, the savings could add up quickly. Note that if you end up using this technique, you must anticipate all controls that might initiate an async postback from within an UpdatePanel (or those marked as async triggers outside the panel) and test for all of those identifiers.
Now, on to the main point of this post – if you're using declarative data sources (like the SqlDataSource or ObjectDataSource) to populate data-bound controls within an UpdatePanel, you can use this same technique to pre-empt the data source from retrieving data if the async postback was not initiated by one of the controls in the UpdatePanel being updated. The technique I use is to add a handler for the Selecting event of the data source, and if you determine that this data source should not bother retrieving data, set the Cancel property of the SqlDataSourceSelectingEventArgs parameter passed into the handler.
<asp:SqlDataSource ID="_authorsDataSource" runat="server" …
OnSelecting="_authorsDataSource_Selecting">
…
// in code behind
protected void _authorsDataSource_Selecting(object sender,
SqlDataSourceSelectingEventArgs e)
{
if (!_getAuthorData) // _getAuthorData populated with t/f based on update panel
e.Cancel = true;
}
So there you go, with a little effort you can not only minimize the data flowing from the server to the client with UpdatePanels, but also the amount of work done on the server.