In light of the rising popularity of AJAX during the last couple of years, Microsoft wanted to include the feature natively into ASP.NET’s object model. They came up with an elegant solution for the feature in ASP.NET 2.0 and they called it Client-Callback.

The elegance of Client-Callback

The elegance of Client-Callback is strongly tied with the simple implementation on aspx web pages. You only need to implement the ICallbackEventHandler interface and add two methods, one method for doing the work and one for sending the response back to the caller. This allows you to execute the two methods asynchronous if you choose. The elegance of the code-behind implementation is only enhanced by the client-side JavaScript code you need in order to call the Client-Callback method. It’s literally only one line of JavaScript code to call it, and one function to receive the response.

What all this means is that it is very easy to start using, because you get all these features out of the box. You still have to write all the logic your self, both the server-side and client-side which can be trickier if you’re not a somewhat experienced JavaScript scripter. But if you are, then you can do magic in a fast and simple way using ASP.NET Client-Callback.

The lack of performance

All of this great functionality comes with a price, and that price is performance. The time between the request and the response is the measure of performance of this feature, and it’s actually not bad for single requests. The slow performance occurs when you do multiple calls on the same page.

Let’s say you have a table of 25 products and when the mouse hovers over the name, an image of that product is displayed right next to the cursor. It’s a nice feature and the website visitors find it useful and try hovering over multiple products in a relative short period of time. The first image is loaded pretty fast, but the rest hangs for a second or more. This is not acceptable because you want it as close to real time as possible.

Finding the solution

I know this particular example because I ran into it last week. I implemented the ICallbackEventHandler and the related methods with the purpose of sending the filename of the image back to the JavaScript caller based on the ID of the product. This table was a server-control that didn’t allow me to add the filename as part of the data source, so I had to use AJAX.

Everything worked like a charm, but the performance was awful as described above. After trying everything from clearing the Page_Load event handler to removing all controls from the page I gave up, but I didn’t accept defeat. So, I wrote a generic handler (.ashx) which only purpose was to write the filename belonging to a product ID. Then I wrote a JavaScript function that used a HTTP request to retrieve the filename from the generic handler.

This approach was much faster than the ASP.NET built in Client-Callback feaature and as close to real time as you can get. The JavaScript function also cached the filenames to the clients’ cache, making it even faster if the same picture was to be shown more than once which I knew they would.

Choosing the right approach

I’ve used the Client-Callback feature many times in a lot of different scenarios without it giving performance issues. But in this case it did and it took me several hours of trial and error before I came up with a solution that basically wasn’t simple at all. Well, not simple compared to the Client-Callback approach and that really bothers me. I’m a keep-it-as-simple-and-clean-as-possible kind of developer and although the solution wasn’t very complex or hard to do, it’s still more complicated.

Even though I love the simplicity of the ASP.NET Client-Callback implementation, I have to admit that I’m probably not going to use it in the future. There’s a lot of great AJAX JavaScript libraries that let’s me keep the simplicity of the client-side code and at the same time harness the raw power of a generic handler. I’m sorry Microsoft, but you killed performance for the sake of simplicity on this one.


Comments are closed