Wednesday 26 January 2011

UpdatePanels - Response Text

So, I've covered the basics of UpdatePanels in a previous post but what exactly makes them so much faster than just normal postbacks? Well the answer is that when the server responds, it doesn't respond with the full HTML of the whole page, instead, it'll respond with only the HTML that it needs to be able to update the content of each UpdatePanel.

This is done using a special format that is read, understood and executed by JavaScript at the client. An example of this response text is here:


175|updatePanel|panel|
                <input name="textbox" type="text" value="Foo" id="textbox" />
                <input type="submit" name="button" value="Submit" id="button" />
            |88|hiddenField|__VIEWSTATE|/wEPDwUKMTg0NjEyNDk1MQ9kFgICAw9kFgICAQ8PFgIeB1Zpc2libGVoZGRkcMaCINs5w9oczWUhLKPVgiBR3uk=|64|hiddenField|__EVENTVALIDATION|/wEWBAKc1c6BDgKsyt74CwLz9r7ABAKw3cLDCSDRvcYZVa7GBSZW2zBXlJJG8Vsa|0|asyncPostBackControlIDs|||0|postBackControlIDs|||16|updatePanelIDs||tpanel,tpanelTwo|0|childUpdatePanelIDs|||5|panelsToRefreshIDs||pa
nel|2|asyncPostBackTimeout||90|12|formAction||Default.aspx|13|pageTitle||Untitled Page|


Now this actually has a specific format, even if it doesn't seem so at first glance. Essentially, it's a concatenation of strings, the breakdown of each string is represented in the diagram below:


In the example above, you can tell roughly, what's going to happen to the page, just by looking at the response text. The content of the update panel whose id is "panel", will be changed to now contain the textbox and submit buttons as defined by the HTML in the response text. It includes the new ViewState value, the IDs of any other update panels contained within the page, the IDs of the update panels to be refreshed and then a few other page level properties like the form action and the window title.

Now we know the format of this response text, we can make use of that knowledge if we ever need to transform our output from the server to the client. For example, you may want to remove all unnecessary white space from the response, or, you may need to change a URL reference and rather than finding each and every instance, you could just change it at the very end of the page life cycle. I'll explain how to do all of this in a future post!

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

Tuesday 18 January 2011

The Start of Something Beautiful?

So, I've finally got around to making my own blog. Why have I decided to do such a thing? Well, I thought it was about time I gave something back to the community.

Let me tell you a little about myself. I've always been interested in programming, ever since I've known what a computer was. Around the age of 14, our family invested in a computer that could actually connect to the internet, back then the greatest connection you could get was over a 56k modem, but none the less, I loved it. As soon as I could connect to the internet, I started to wonder.... how do hit counters work? How does the time get stamped on the Yahoo! website? Come to think of it, how on earth do you make a website? And so, I set out to learn such things, I looked up articles online, I bought books and over a period of time, I taught myself JavaScript, HTML, PERL and PHP. This knowledge would stand me in good stead for the future, the JavaScript and HTML proving to be invaluable in my current job

Well, I then and got a few A Levels and headed off to the University of Essex to study Computer Science where, I tried to study just about every programming course I could get my hands on but, due to my fascination with the Internet, I chose to specialize in Internet Technology where I had the pleasure of looking at C, C++, Ruby on Rails, Java (and the internet tech that uses Java e.g. servlets, JSP, applets) and finally, ASP.NET.

I graduated University with a first class degree with honours and set out into the big wide world where a company that specializes in property management software was kind enough to hire me as a software developer. When I first started, they were primarily using Oracle Forms, a technology so old, I hadn't even heard of it. Fortunately, plans had already been made to migrate from Oracle Forms to a web application using ASP.NET WebForms as the platform to develop for. I was fortunate enough to be involved in that project. That project started 2.5 years ago and is still on going, as I'm sure you can imagine, moving ASP.NET suddenly gave us a whole range of things that could be done which just wasn't possible on the old technology stack so, we started implementing cool new features. My internet technology background put me in a good position for this and so I've been involved in developing things that, if I'm honest, I didn't even know was possible 2 years ago. These mini projects have thrown up all sorts of issues, some of which, I think, would be beneficial to share with the community.

Maybe someone else will stumble across the same problem(s) and use this blog to find a solution, maybe someone can come up with a better solution, maybe someone can find ways to improve my solutions. These are the reasons I want to share my experiences with you and so, Clements Code (a name which I truly hate by the way) was born.