Saturday 22 January 2011

The Beauty of UpdatePanels

So, my first ever technical blog post… here goes…

UpdatePanels are, in a word, fantastic. For those of you that haven’t had the pleasure of using them before, they give an ASP.NET WebForms developer a simple way of performing AJAX calls. This allows you to update parts of your web page, requiring no page load. Which means no white flicker as the page re-renders and, more importantly, it’s faster than a full page load!

So, how do you use one?  Well, an UpdatePanel can get a little advanced, but the basics are as follows…

Firstly, you need a ScriptManager control. These things are pretty cool too, they provide the JavaScript functions needed for an UpdatePanel to work, they also allow you to use PageMethods (that’s a future blog topic) and make globalization a little easier.

Secondly, unsurprisingly, you need your UpdatePanel control. This needs to be wrapped around the content you want to update using an ajax call. So, as an example, take the following:

<asp:TextBox ID="tb" runat="server" Text="Hello" />
<asp:ScriptManager ID="scriptManager" runat="server">     
</asp:ScriptManager>
        
<asp:UpdatePanel ID="panel" runat="server" UpdateMode="Conditional">
    <ContentTemplate>
        <asp:TextBox ID="textbox" runat="server" Text="Foo" />
        <asp:Button ID="button" runat="server" Text="Submit" />
    </ContentTemplate>
</asp:UpdatePanel>

So, now, any control that causes a postback that sits inside the UpdatePanel will cause a partial page postback, using an AJAX call, and only the content of the UpdatePanel will be updated. So, using that knowledge, I'm now going to place the following handler on the click event of the button:

void button_Click(object sender, EventArgs e)
{
    this.textbox.Text += " Bar";
    this.tb.Text += " World";
}

What do you think will happen?

Yep, you're right. The TextBox outside the panel will still read "Hello" but the TextBox inside will read "Foo Bar". You'll notice that the full page life cycle still takes place, it has to to ensure the controls object gets created, however, the data sent back to the client only includes the data used to update the UpdatePanel, this leads to a significant amount of time and bandwidth saved.

Now, at first, this sounds fantastic, but it can result in a few odd errors, one of which I'll show you now. The errors stem from the problem that when you change certain properties of controls outside of the update panel you're updating, then the server expects these controls to retain these properties on postback, however, the data it's sent back from the client is still holding the old properties and so, we have a problem.

Take this example, if we change the button_Click method to this:

void button_Click(object sender, EventArgs e)
{
    this.tb.Visible = false;
}

Now, when you hit the button twice, you'll get a JavaScript error message (Assuming you have debugging turned on) which states the following:

Sys.WebForms.PageRequestManagerServerErrorException: Invalid postback or callback argument.  Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page.  For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them.  If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.

Cutting a long story short, the data sent from the client, to the server, includes a textbox that the server thinks shouldn't be there (you've just made it invisible after all.) and so, when it tries to validate the data, it fails. This can happen with other controls too, with different properties, for example, if you change the Items within a DropDownList and don't update then that can cause problems. It's just something you have to look out for. In complicated systems, it can become a bit of a pain.

Anyway, the last, very helpful feature of UpdatePanels is that you can force an update of any UpdatePanel, take this code for an example, we add an extra UpdatePanel to the code above:

<asp:UpdatePanel ID="panelTwo" runat="server" UpdateMode="Conditional">
    <ContentTemplate>
        <asp:TextBox ID="textboxTwo" runat="server" Text="Code" />
    </ContentTemplate>
</asp:UpdatePanel>

Now, if we change the button_click method to this:

void button_Click(object sender, EventArgs e)
{
    this.textbox.Text += " Bar";
    this.label.Text += " World";


    this.textboxTwo.Text += " Bye";
    this.panelTwo.Update();
}

Both UpdatePanels will be updated. It's also possible to ensure that an UpdatePanel is updated on every postback by changing the UpdateMode to Always.

Ok, that's my brief overview. I've missed out A LOT of information, some of which I'll cover in detail in future blogs but hopefully that should be enough to get you started.

Let the AJAX fun begin!


For further reading, try some of these articles:
http://msdn.microsoft.com/en-us/library/bb386454.aspx
http://msdn.microsoft.com/en-us/magazine/cc163413.aspx#S1
http://www.asp.net/ajax/tutorials/understanding-asp-net-ajax-updatepanel-triggers

No comments:

Post a Comment