Simplify calling ASP.NET AJAX services from jQuery
AJAX, ASP.NET, JavaScript, jQuery By Dave Ward on July 21st, 2009As 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:
$.ajaxSetup({ type: "POST", contentType: "application/json; charset=utf-8", data: "{}" });
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:
$.ajaxSetup({ type: "POST", contentType: "application/json; charset=utf-8", data: "{}", dataFilter: function(data) { var msg; if (typeof (JSON) !== 'undefined' && typeof (JSON.parse) === 'function') msg = JSON.parse(data); else msg = eval('(' + data + ')'); if (msg.hasOwnProperty('d')) return msg.d; else return msg; } });
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:
$.ajax({ url: "HelloWorld.asmx/Hello", success: function(msg) { console.log(msg); } });
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?
Similar posts
What do you think? Your comments are welcome.
I appreciate all of your comments, questions, and other feedback, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums instead.
If you're replying to an existing comment, please use the threading feature. To do this, click the "Reply to this" link underneath the comment you're replying to.
10 Mentions Elsewhere
- DotNetShoutout
- DotNetBurner - ASP.net Ajax
- Reflective Perspective - Chris Alcock » The Morning Brew #395
- [Link List] jQuery, Agile, WCF REST, WF, OpenXML, Live Messenger Anniversary, Wallpapers | I love .NET!
- Simplify calling ASP.NET AJAX services from jQuery
- Creating a Webservice Proxy with jQuery « Life of a geek and a part-time poet
- Populating Table Data using jQuery – My Tech World
- [Link List] jQuery, Agile, WCF REST, WF, OpenXML, Live Messenger Anniversary, Wallpapers | Guru Stop
- Nathan Prather » Good JQuery Helper Functions
- links for 2010-09-01 « dstelow notes…


Thanks for the post. I’ve been using helper methods in the past, but am now going to start using this technique, especially for the native JSON parsing.
Thanks again, and keep up with the posts. Love your blog.
I haven’t really used $.ajaxSetup much because I don’t see the need to globally set this configuration data on a static instance. This really isn’t more or less work than creating a wrapper function which IMHO is better choice because it doesn’t set global config values that might interfere with something else on the page.
Either way you end up configuring pretty much the same settings so the amount of code is roughly the same.
One nice thing about $.ajaxSetup is that you can trick plugins (a few autocomplete plugins come to mind) to play nice with ASP.NET AJAX services.
Thanks for the great post Dave ;-)
Being a n00b, does jQuery have namespaces regarding $.ajaxSetup? If so, you could define the defaults to a non-default namespace which you would use but other functionality, like $.getJSON, wouldn’t.
No. All of the shortcuts are just wrappers around various usages of $.ajax.
Like the post but where do you set the $.ajaxSetup ? Do you have it in a seperate file that is included in all pages or do you change the jquery file (I doubt this)?
Cheers
It’s part of jQuery.
This is interesting solution. But anyway you will need some plugin (helper) to set data in more beautiful way (comparing to simply combining strings).
How you deal wuth this issue? Some helper or plugin?
I am using old jquery ajaxdotnet plugin but may be there are some better ideas (have also seen Rick’s ServiceProxy solution)
Often, you’ll use a plugin like jqGrid or DataTables to render the data. Otherwise, something like jTemplates is nice. I wrote a post about that recently: http://encosia.com/2008/06/26/use-jquery-and-aspnet-ajax-to-build-a-client-side-repeater/
I mean not only rendering response but constructing request data. Because every time calling JSON2.stringify(params)is not so great idea and combining strings to create complex request parameter is even worse.
You can simplify the calling process a bit with a combination of a DTO and JSON.stringify: http://encosia.com/2009/04/07/using-complex-types-to-make-calling-services-less-complex/
This is a great idea. I’m wondering how this approach could be used with the official jQuery autocomplete plugin for calling ASMX web services (as Dave Ward suggested). The current problem is that autocomplete always uses GET (with query string parameters), which causes ASMX web service to return XML instead of JSON data. This would be really helpful.
It’s a bit of a pain, but yes you can do that with this. You have to set an $.ajaxSetup with contentType, type, and a beforeSend handler to convert the data parameter to JSON before it POSTs.
That particular autocomplete plugin is one case where I suggest using an HttpHandler instead.
Thank you for the response, Dave. I’m actually debating with myself what’s the best way of using this plugin. I was thinking about HttpHandler, but I don’t know how to make it return JSON data (will need to do more search). Also, if I understand it correctly, I would need to create a separate file for each autocomplete search operation (unless I use some additional query string parameter, and then perform logic based on its value, which is not very elegant). Will keep looking. (Off the topic: Thanks for the info in your blog; very helpful.)
Jorn’s autocomplete plugin actually prefers the data be returned as pipe delimited data, with one record per line, so an HttpHandler is pretty straightforward. I believe you would require separate handlers per autocomplete though, since it doesn’t allow you to provide any context other than the prefix from the input field.
Depending on your requirements, some of the other autocomplete type plugins are much more JSON friendly. This one is nice, for example: http://devthought.com/projects/jquery/textboxlist/
Thanks again Dave. I appreciate the feedback. I just tried using HttpHandler and it seems to work. Now I need to find a sample showing how to deserialize JSON so that autocomplete does not choke (I think I saw a couple of examples). Textboxlist is nice, but I think it’s more than I need, and it’s not free for commercial use (I do not really care about the cost, it’s very small, but about the license handling issues, etc; it’s too much hassle on my corporate side).
nice article, allways welcome anything that shortens the code, particularly that I am weak in javascript.
one question thought, since I’m not following the term “asp.net ajax” I don’t really know what it is (using only jquery lightly), but is it possible to apply this knowledge to WCF?
e.g. my application is handling with WCF services, does JQuery offers something to it as well?
this is one awesome blog, I don’t know If I can find more on AJAX topic than here (nice thing as this is not my field)
In the context of using jQuery to call services, when I say ASP.NET AJAX, I mean the server-side extensions (“ScriptServices”, page methods, JavaScriptSerializer, etc).
Using WCF, you only need to worry about the content-type issue if you’re using AspNetCompatability mode (in which case it acts much like an ASMX “ScriptService”). Otherwise, you can probably just use $.getJSON or $.post to call your services through jQuery.
The browser-native JSON parsing is something you may find helpful though, even in WCF.
just wanted to thank you for reply. Appreciated. Not only you have nice blog full of AJAX info but you also are replying to every comment.
bookmarked :D (and no I somehow hate RSS;p)
Hi Dave, in my current project I use “dataFilter” to convert the Date type, like this:
After reading your article I changed my codes to this:
But there will throw a SyntaxError, I think that is because of the “JSON.parse” cannot parse the string like “new Date(xxxx)”.
Could you give me some advices about the Date type parsing with Native JSON?
JSON can serialize a Date object to a string:
How to parse the above JSON string to Date object simply?
P.S: I hear about the “.d” issue for the first time because I use ASP.NET 2.0 all the while, thanks for your article.
What to do if you have included the json2.js script on your site, to use JSON.stringify()? then JSON is also not undifined, or am i wrong?
If you have json2.js included, it’s okay to let it handle the JSON.parse. It uses eval() in the end, but attempts to sanitize the string a bit first. So, it’s preferable to the blind eval() anyway.
You are voted!
Track back from WebDevVote.com
Great work, your posts are so valuable.
one question that i have been searching for , what if I create one Page that will carry all my WebMethods and call it from my other pages , it seem to me like there is no performance problem as both are called the same way.
please correct me if I am wrong.
You can do that. Page methods don’t check/require that the request originate from the ASPX that they reside on.
However, if you want to create centralized functionality to be reused, I’d suggest a web service instead of page methods. They’re functionally almost identical, but the web service will express your intent more clearly.
thanks a lot for your reply,
so WS will be better performance wise or its just a better way to organize the app. because it seem to me that the webMethod is much cleaner especially with the way you explain using it with jQuery.
in fact after reading your posts I removed all Ajax Toolkit usage
You can use an ASMX service’s WebMethod in the same way (with the same jQuery syntax). Page methods actually act as ASMX “ScriptServices”, not the other way around.
This is an example of using jQuery to call an ASMX web service: http://encosia.com/2008/03/27/using-jquery-to-consume-aspnet-json-web-services/
thanks a lot for your time, keep up the good work
Dave,
I am just staring this JSON thing but can not get it to work. I add a new webservice but i try to call the Helloworld default webmethod but it just errors!
All i ahve on my page is a button:
If i take out the contentType: “application/json; charset=utf-8″, it will sucseed but the eval doesnt work properly.
Can you point me to (or write) a tutorial on setting up the webservice for this. I tried following one on code project but that doesnt work.
Thanks
If you’re just getting started, take a look at these posts (in this order):
Using jQuery to Consume ASP.NET JSON Web Services (be sure to see the source download on this one too)
3 mistakes to avoid when using jQuery with ASP.NET AJAX
A breaking change between versions of ASP.NET AJAX
That should get you up to speed.
Thanks dave, its working now, i missed the [ScriptService] off my webservice. This way meakes things runa alot faster!
Keep up the good work! :)
Hi Dave,
Do you have any idea how to set a jtemplates template using a web method? I have a web method that returns a template (I need to be able to replace certain text in the template with localized text, so I have to process the template before it gets returned to the page)
Here’s what I tried without success:
GetTemplate() does not take any parameters. What am I doing wrong?
Hi Joel,
Not sure if I’m correct here but I’m sure you can use setTemplate with HTML defined in your page. I think it might be possible to return the HTML using the web method and then set the template to the returned HTML.
Make sense?
Thanks Jon. I’ll give that a try.
That’s how I would do it as well.
You won’t easily be able to use setTemplateURL against an ASMX service. There’s no way I know of to make an ASMX service directly return HTML with no XML or JSON wrapper around it.
I see what you mean. Thanks for your input, Dave.
Hi,
I am using JQuery+ Pagemethods for most of my ajax needs. Its excellent but now I have a problem with https page..
I have a captcha refresh script in my registration page and the refresh will happen through JQuery/Pagemethod.. Its working excellent without HTTPS but when I made my registation page SSL, the AJAX call is showing error 500 with following Response
{“Message”:”Authentication failed.”,”StackTrace”:null,”ExceptionType”:”System.InvalidOperationException”
}
Do you know how to solve this?
Thanks and Best Regards
Anz
Did you also change the URL of your $.ajax() call to use HTTPS? Calls will fail if the protocol of the page and $.ajax URL don’t match.
great article .i have a question.you said “Fixing that problem wasn’t difficult, but it also wasn’t immediately obvious what had caused the issue in the first place”
could you please tell us about the fix.how i can use the default settings with j templates ate the same time.
I edited jTemplates’ processTemplateURL function to use an explicit $.ajax() call with the correct parameters, instead of $.get() that it uses by default.
I’m not seeing where there’s a $.get() call in the processTemplateURL function (version 0.7.8). Can you be more specific in the change made to jTemplates?
You’re right, there’s no $.get() in the latest version. Looks like that changed in 0.7.5.
$.ajaxSetup shouldn’t override that explicit GET, but the contentType still needs to be explicitly specified there in the options array.
I must edit latest jTemplate’s source (0.7.8) adding on every jQuery.ajax call (if needed)
jquery, web services, json, jtemplate… is good and fast solution!
I was having issues getting jQueryUI tabs to work in ajax mode and then I realized I had included $.ajaxSetup in my Master Page with defaults for type (POST), contentType (json), dataFilter (for .d) etc.
I changed my ajaxSetup as follows, and now UI Tabs work fine in ajax mode and thanks to Dave, I don’t have to worry about .d either :)
I don’t understand something.
When I use .getJSON doesn’t it parse my json?
Should i use the eval? DOes jquery uses the JSON.parse?
$.getJSON is just a shortcut wrapper around a particular $.ajax call. Under the hood, they all work the same way (and $.ajaxSetup affects them all).
jQuery doesn’t use JSON.parse yet, but will in the next release (the change is already checked in, just pending a release). It currently uses eval() for any JSON parsing.
Now that jQuery 1.4 has been released and uses JSON.parse natively, is the dataFilter no longer necessary?
I think I actually answered my own question! First time for everything :)
Anyways, in my testing with jQuery 1.4, the dataFilter you outline works just fine if msg.d contains JSON.
However, if msg.d contains a simple string value (e.g. HTML), then the dataFilter in combination with jQuery’s post-filter JSON parsing will throw an exception IF the ajax dataType option is “json” or if you don’t specify a dataType and the contentType contains “json”.
According to the jQuery 1.4 documentation for the ‘dataType’ option: “If no dataType is specified, jQuery will intelligently try to get the results, based on the MIME type of the response.”
Since you need to specify a contentType (MIME type) of ‘application/json’ when working against ASP.NET webservices, jQuery will attempt to parse msg.d as JSON, even if it’s just a string.
So, and maybe this is just good practice anyways, with jQuery 1.4 be sure to set the ‘dataType’ option in your ajax request to “html” or “text” if msg.d is going to contain a string value. Only set the ‘dataType’ option to “json” if msg.d is going to contain JSON (properly formatted).
Hope this makes sense and helps someone else!
P.S. Thanks for all the great posts Dave, your site is a fantastic resource!
Adam, thanks a lot – you saved me a lot of time. I’ve just migrated to jQuery 1.4 and some of my service calls started failing. But then I found your post and it’s now clear as day.
Adam, you got it. This is a pain as it’s broken my app all over! Thanks for explaining.
Dave,
I think the dataFilter approach you show here has a serious issue if you are returning a string value result (or a date encoded as string). The problem is that jQuery parses the result from the dataFilter function again using JSON parsing (if the dataType=”json”):
which means that any string result will fail with a parser error as it’s effectively double parsed.
Bummer cause there appears to be no workaround for this. Fixable if instead of type they’d use s.dataType so that the dataFilter function could change the type to “text”.
Another issue is that you probably would want to somehow filter the dataFilter function so that you’re only doing this conversion for JSON responses. I use:
Otherwise every AJAX call even if it returns script or text/html will encode into JSON which is definitely a problem if you use a global filter and if other plugins are used that might make their own internal AJAX callbacks to retrieve script or other support files.
Yeah, the changes in jQuery 1.4 complicate this a bit.
Setting $.ajax()’s dataType parameter to “text” (or anything) solves the issue of handling invalid JSON. Since that’s just an arbitrary string that gets passed around, you can take it one step further and solve both problems fairly elegantly like this:
I haven’t used that widely, but did implement it in one project (where I had a conflict with plugins, as you mention) with solid results.
Yup that’s pretty much what we can do for CUSTOM parsing that we control. (like a proxy for Web Services/PageMethods etc.). But that won’t work for the generic jQuery case for calls $.getJSON() or $.ajax() calls that do have “json” set as the datatype.
Not critical, but would be nice if there was a solution for this. More info on this issue here on the jQuery forum:
http://forum.jquery.com/topic/datafilter-function-and-json-string-result-problems#14737000001336005