Pages

Wednesday, July 22, 2009

Simplify calling ASP.NET AJAX services from jQuery

AJAX, ASP.NET, JavaScript, jQuery By Dave Ward on July 21st, 2009

As jQuery’s popularity in the .NET community has risen over the past year, one recurring theme I’ve seen is the desire to refactor away the details of using it to call ASP.NET AJAX services. Whether through helper function or specialized jQuery plugin, I’ve seen numerous methods proposed and/or in use.

Personally, the syntax never bothered me. The contentType parameter is ugly, but I have a Visual Studio code snippet for the $.ajax call and rarely think about it.

That came to an end earlier this year, when I started using dataFilter. I needed to isolate my code from the “.d” issue, and wanted to take advantage of browser-native JSON parsing in Firefox 3.5 and IE8, which required a bulky dataFilter.

Repeating that entire callback function in every $.ajax call was not acceptable. So, I was happy to learn that jQuery provides an excellent solution for consolidating settings to be used in multiple instances of $.ajax.

In this post, I’ll show you how to use that consolidation feature, and exactly how I am now using that to more simply call ASP.NET AJAX services with jQuery.

Configuring $.ajax’s default settings

Rather than wrapping the $.ajax call in a plugin or helper function, jQuery provides a built-in solution that I think is a better alternative:  $.ajaxSetup.

$.ajaxSetup accepts an array of settings that allows you to supply defaults for any of the parameters that you would set in an $.ajax call. Settings like contentType, type, and dataFilter are all fair game, for example.

Using this function, it’s easy to set jQuery’s $.ajax defaults to match the refined settings that we worked out together last year:

   1:  $.ajaxSetup({
   2:    type: "POST",
   3:    contentType: "application/json; charset=utf-8",
   4:    data: "{}"
   5:  });



Because parameters to $.ajax override these defaults, presetting “data” to an empty JSON string is safe. Any $.ajax call that does specify a data parameter will function as expected, since the default will be ignored.

The particular issue caused by forgetting the empty data parameter can be difficult to track down, and only shows up after you’ve deployed your application to IIS. So, having the default as a safety net is recommended.

Adding JSON parsing improvements

Because $.ajaxSetup also supports setting a dataFilter, adding the “.d” isolation and browser-native JSON parsing from my last two posts is easy:

   1:  $.ajaxSetup({
   2:    type: "POST",
   3:    contentType: "application/json; charset=utf-8",
   4:    data: "{}",
   5:    dataFilter: function(data) {
   6:      var msg;   if (typeof (JSON) !== 'undefined' && 
   7:          typeof (JSON.parse) === 'function')
   8:        msg = JSON.parse(data);
   9:      else
  10:        msg = eval('(' + data + ')');   if (msg.hasOwnProperty('d'))
  11:        return msg.d;
  12:      else
  13:        return msg;
  14:    }
  15:  });



This dataFilter processing is actually what pushed me to start using $.ajaxSetup in all of my own projects. It was one thing to accept multiple contentType and method declarations, but repeating the dataFilter for every $.ajax call was more than I could handle.

Putting it to work

With the ASP.NET AJAX defaults set in $.ajaxSetup, all that’s required to call a “ScriptService” or page method is the URL and a success callback:

   1:  $.ajax({
   2:    url: "HelloWorld.asmx/Hello",
   3:    success: function(msg) {
   4:      console.log(msg);
   5:    }
   6:  });



In fact, even the success callback is optional. For example, if you were periodically pinging a “heartbeat” service to keep the user’s session alive, $.ajax would only need the service’s URI.

This more concise syntax makes your service calls far more readable, especially for developers who aren’t familiar with the content-type required by ASP.NET AJAX.

Caution: Sometimes it works too well

While this is a handy way to simplify calls to ASP.NET AJAX services, do understand that $.ajaxSetup applies to all of jQuery’s AJAX derivatives. Setting the default HTTP method and content-type may also impact code and plugins that use jQuery’s built-in communication functionality (e.g. $.getJSON, $.post, etc).

For example, I often use jTemplates as a client-side templating solution. Because its processTemplateURL routine relies on $.ajax to retrieve remote template files, setting the ASP.NET AJAX content-type and POST method in $.ajaxSetup breaks that functionality of jTemplates.

Fixing that problem wasn’t difficult, but it also wasn’t immediately obvious what had caused the issue in the first place. In my experience using this technique, the undesirable side effects are rare enough that it’s not a serious concern, but do be aware of the potential.

Conclusion

I’ve been using this in production for several months now, with great results. Users have noticed the increased speed that came with browser-native JSON parsing, the “.d” isolation has reduced regression errors due to some code we run on both 2.0 and 3.5 servers, and it requires less effort on my part to do all that.

What do you think? Is this helpful?

Would a Visual Studio template with this rolled in be something you would use?

 

Original post can be found here