Michael Monteleone

Proxying ASP.NET AJAX events with jQuery

MVC is great, but ASP.NET remains. Web Forms walk amongst us. Not alive, not dead. (Not even LINQ to SQL-Dead.) William Faulkner, who never maintained a legacy ASP.NET codebase, gets it right:

The past is never dead. It’s not even past.

But as code has grown, so have tools for its manipulation. jQuery excels here. It’s great for bulk-shoveling client-side mass.

Here we’ll see an example of this by proxying ASP.NET AJAX’s client-side events as native jQuery events using jQuery’s Special Event API and some fancy JavaScript meta-programming.

Scenario

So, you’re faced with an UpdatePanel and need to post-process its results. Maybe you want to reveal the UpdatePanel’s response through an animation. Sure, you could use the ASP.NET AJAX Control Toolkit, but maybe you’re already using jQuery, having learned that the toolkit’s server-side savings tend to cost you on the client, or maybe you want to do something deeper like re-wiring the response’s particular content with other client-side logic.

Ideally, you could get by with jQuery event delegation, but maybe it’s just out of practical bounds in your scenario. So, it’s back to tying directly into ASP.NET AJAX’s client side code.

Here’s how you could do it by the book:

But you’re using jQuery, and the impedance mismatch and explicit dependence on the AJAX toolkit is less than pleasant. Paraphrasing Rob, “impedance mismatch is death by a thousand cuts.” You’d probably prefer:

Solution

That’s easy to allow for with the aid of jQuery Special Events. Many people tend to equate jQuery plugins with with extending the jQuery.fn object, but fewer are familiar with extending jQuery’s events via the Special Events API. Though much has been written about the Special Events API, I’ve found it easiest to understand as simply a mechanism for executing code upon the actual binding or unbinding of a given event.

So, $(document).bind('atlasEndRequest', function(){...}) is not only binding a callback to a custom event, it’s also setting up background logic to properly raise the atlasEndRequest custom event when necessary.

This will work as-is. But special events can also have code run upon the last unbind of an event from a selection with teardown, or (new in 1.4) upon each bind and unbind of an event from a selection with add and remove. And the PageRequestManager gives us more possibly-useful events (initializeRequest, beginRequest, endRequest, pageLoading, pageLoaded) we might want to proxy as well. So, with a little bit of fancy meta-programming, we can support all of them, along with proper unbinding.

A bit of code, but dig in. You’re smart. And two extra credit points:

It provides shortcut methods for binding and triggering the events, so

is aliased

And it uses some fanciness with a self-reassigning-function to ensure that absence of the Sys.WebForms.PageRequestManager will not break the plugin, and getting its instance will only necessarily be called once. It’s a micro-optimization for sure, but still a fun example.

If you are still interested in the sender and args parameters passed back from the PageRequestManager to its event handler, those are still exposed via the optional data parameter.

Even if you don’t find this particularly useful or practical, hopefully it opens your mind to JavaScript’s yoga-like flexibility. _why:

Not all code needs to be a factory, some of it can just be origami.

You can grab this plugin along with its small test suite from GitHub.

← Suspiciously Pleasant XML with C# 4

blog comments powered by Disqus