3 mistakes to avoid when using jQuery with ASP.NET AJAX
AJAX, ASP.NET, JavaScript, jQuery By Dave Ward on June 5th, 2008Over the past few weeks, I think I have definitely embodied Jeff Atwood’s claim that we’re all amateurs, learning together. Despite my best efforts to thoroughly test before posting, a few problems slipped through in my recent posts about using jQuery to consume ASP.NET JSON serialized web services and using jQuery to call ASP.NET AJAX page methods.
On the bright side, your great feedback in both posts’ comments has reinforced the fact that some of the best content on my blog is the part that you write.
In this post, I’m going to detail three of the problems that were discovered as a result of those previous two posts:
- An extra requirement when making a read-only request to IIS6+.
- An oddity in Internet Explorer 7’s XmlHttpRequest class.
- A common mistake when passing JSON parameters through jQuery.
Finally, I’ll suggest what I now believe to be a best practice usage, taking all of these issues into account.
Security requirements when POSTing to IIS
This error message was the most common problem that was reported:
Length Required
The underlying issue is that most installations of IIS6+ require a content-length be provided with all POST requests, even if there is no content (POST data).
The content-length for a request with no data should be 0, but jQuery doesn’t set that header automatically unless there is a data parameter. Since ASP.NET AJAX’s JSON serialized services require a POST request, this becomes a stumbling block for read-only requests.
The easiest way I’ve found to work around this is to use an empty JSON object as a parameter on read-only requests. For example, if you were calling a page method:
$.ajax({ type: "POST", url: "PageMethod.aspx/PageMethodName", data: "{}", contentType: "application/json; charset=utf-8", dataType: "json" });
This will cause jQuery to correctly set a content-length of 2, while your web service or page method will happily ignore the empty parameter and treat the request as read-only.
You might notice the content-type is set differently in this example than in my previous posts. More on that next:
A problem with Internet Explorer and XmlHttpRequest
Previously, to call ASP.NET AJAX services with jQuery, I suggested this usage:
$.ajax({ type: "POST", url: "WebService.asmx/WebMethodName", beforeSend: function(xhr) { xhr.setRequestHeader("Content-type", "application/json; charset=utf-8"); }, dataType: "json" });
The reason for the beforeSend delegate is due a quirk in jQuery which causes it to send a specified content-type only if there is also a data parameter specified.
For security reasons, ASP.NET AJAX will not provide a JSON serialized response unless the proper content-type is provided. By using the beforeSend delegate as shown, the content-type will be manually set on the XmlHttpRequest object, before the request.
However, the new XmlHttpRequest class in Internet Explorer 7 doesn’t implement setRequestHeader very intuitively. Instead of setting the specified header, it appends the value.
This becomes a problem when you make a request that includes a data parameter. When POST data is provided, jQuery will automatically set the content-type to its default of application/x-www-form-urlencoded. In the beforeSend delegate, the required application/json; charset=utf-8 will be appended after jQuery’s default.
End result? Because this amalgamation of content-types isn’t what ASP.NET AJAX expects, the web service will not return JSON serialized content and jQuery will be unable to parse it.
Solution? If you’re sending data in your request, use jQuery’s contentType parameter to set the content-type, so that the default is never added:
$.ajax({ type: "POST", url: "WebService.asmx/WebMethodName", data: "{'fname':'dave', 'lname':'ward'}", contentType: "application/json; charset=utf-8", dataType: "json" });
JSON, objects, and strings: oh my!
In requests made to them, ASP.NET AJAX script services and page methods understand and expect parameters serialized as JSON strings. These parameters are parsed out of the POST data and used as arguments to the method you’ve called.
However, if you directly provide a JSON object as the data parameter for an $.ajax call, jQuery will attempt to serialize the object instead of passing it on to your web service.
Take this sample request, for example:
$.ajax({ type: "POST", url: "WebService.asmx/WebMethodName", data: {'fname':'dave', 'lname':'ward'}, contentType: "application/json; charset=utf-8", dataType: "json" });
Because that data parameter is a valid JSON object, calling the web service this way won’t throw any errors. Unfortunately, it won’t have the desired result either. Instead of passing that JSON object through to the web service, jQuery will automatically serialize and send it as:
fname=dave&lname=ward
To which, the server will respond with:
Invalid JSON primitive: fname.
This is clearly not what we want to happen. The solution is to make sure that you’re passing jQuery a string for the data parameter, like this:
$.ajax({ type: "POST", url: "WebService.asmx/WebMethodName", data: "{'fname':'dave', 'lname':'ward'}", contentType: "application/json; charset=utf-8", dataType: "json" });
It’s a small change in syntax, but makes all the difference. Now, jQuery will leave our JSON object alone and pass the entire string to ASP.NET for parsing on the server side.
Best practice? I hope so this time!
Taking these three caveats into account, I think this is the best practice for calling read-only ASP.NET AJAX web services via jQuery:
$.ajax({ type: "POST", url: "ServiceName.asmx/WebMethodName", data: "{}", contentType: "application/json; charset=utf-8", dataType: "json", success: function(msg) { // Do interesting things here. } });
When consuming web services that require parameters, the usage is similar. Just make sure that you’re passing a JSON object in a string:
$.ajax({ type: "POST", url: "ServiceName.asmx/WebMethodName", data: "{'fname':'dave','lname':'ward'}", contentType: "application/json; charset=utf-8", dataType: "json", success: function(msg) { // Do magic here. } });
In either of these cases, substitute PageName.aspx for ServiceName.asmx and PageMethodName for WebMethodName if you want to call a page method instead of a web service.
Conclusion
I hope this post will help you to avoid these common problems when using jQuery with ASP.NET AJAX. I think there’s a great synergy between the two that is certainly worth jumping through these few hoops.
I’d especially like to thank Martin and Ryan for their invaluable feedback, leading to two of the three solutions posted above.
If you’ve run into related problems yourself, I’m eager to hear about them. Please don’t hesitate to comment if you think I’m still missing something important.
Similar posts
What do you think? Your comments are welcomed.
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. If you post there and then contact me with a link to the post, I'll try to take a look at it for you.
If you're replying to an existing comment, please use the threading feature. To do this, click the "Reply to this comment" link underneath the comment you're replying to.
Trackbacks
- Dew Drop – June 5, 2008 | Alvin Ashcraft's Morning Dew
- Interesting Finds: 2008.06.06 - gOODiDEA.NET
- 3 mistakes to avoid when using jQuery with ASP.NET AJAX
- Pathfinder Development » Pitfalls of Using JQuery with ASP.NET Ajax
- Jamie Thompson » Tips for Using JQuery with ASP.NET Ajax
- Wöchentliche Rundablage: Silverlight 2, WPF, ASP.NET MVC, jQuery… | Code-Inside Blog
- Weekly Links: Silverlight 2, WPF, ASP.NET MVC, jQuery… | Code-Inside Blog International
- More jQuery with Ajax/Json : { null != Steve }

Comments
Thanks for the clarification, it will save a lot of time for people just trying to figure it out for the first time. I was keeping the ScriptManager on my pages solely for the ability to call PageMethods and now I’m able to remove it completely.
Any advice on the best way to send and receive objects?
For serializing and deserializing objects on the client side, check out the JSON2 library.
Dave, thanks for the article, it’s very useful to see those 3 items listed on one page. I’m in the process of using jQuery and asp.net web services after reading your previous post on why the update panel is dangerous.
Thanks Dave. It was the third case you documented (string formatting) that caused me real problems for a while, eventually I figured it out but it wasn’t obvious!
Calling web services from jQuery instead of having to use the full ASP.NET Ajax libraries is a great option.
Great stuff, although i have a problem.
I am injecting Json to my CMS, i do rewrite urls.
since some of the stuff i want to do with the ajax call i related to the page itself. i sent lets say pagename.html/get_date which gets rewrited to page.aspx?id=100&/get_date.
doing it this way i do get a response with the page content, not the webmethod return.
any hints on how i could access the pagemethod??
i am in net 2.0
Also messing around with both, my cms and the article code. i seemed not able to call the div from a Webpart.
yes let complicated a bit!!!!.
Thanks from your help in adavance
In that case, I would suggest using a separate web service, and make sure *.asmx is excluded from the URL rewriting.
Thanks, Dave.
i wonder about that approach, but i still can see how could i used the page data from the service, since the webservice is not page-context-aware.
my problem comes when in a webparts portal enviorement i try to call a webpart method from a page so i need that page to load in order to get the properties-webpart-centric-data to interact with the method.
i a way i just want to get away from update panel altogether and use jquery-json to do all the work for me.
the webservice approach i could use to the drag-and-drop functionlity,keeping the new order in memory until the page is requested again.
i keep researching, will post some code when done.
thanks
Great post Dave! I want to thank you for putting in so much leg work under using jQuery as an alternative to or along side ASP.NET Ajax. Keep up the good work.
Awesome follow-up Dave. Between your posts and Rick Strahl’s I’ve been motivated to use jQuery whenever possible and avoid the huge overhead of the MSAJAX library/toolkit — with the side benefit of being able to use these same techniques for my PHP clients as well.
Thank you for the awesome info!!! I am in the process of refactoring much of my code with the goal of eliminating ScriptManager, and am quite excited about it.
One additional requirement that I had was that some of my web service methods return a DataSet object (for use in Ext-JS grids), and when ASP.NET serializes a DataSet to JSON, it encodes the date as a string in the format “Date( 02348293482 )” (or similar), which did not evaluate properly.
To fix this, I extended the jQuery httpData() method to replace those dates with text that will, when evaluated, result in an actual Javascript Date object, like so:
Anyhow, thanks again for the wonderful info, it’s been incredibly helpful!!!
DOH! I just now realized that using a prefilter function is already provided for, and would be better than extending the httpData method… As you say, we are amateurs learning together, haha. Well, I am sure you get the idea :)
And the biggest mistake of all. Mixing ASP.NET AJAX with jQuery! :) Seriously I’ve given up on ASP.NET AJAX, the other AJAX Libraries like jQuery offer better performance. Why not cut out ASP.NET AJAX altogether?
That’s essentially the point of this. You can substitute jQuery for the ASP.NET AJAX client framework this way, if you aren’t using UpdatePanels or toolkit extenders.
There’s no reason to avoid ASP.NET AJAX on the server side though. Letting it handle JSON serializing your services is just one less thing you have to worry about. Being able to write page methods is handy too.
Right… I’m using WCF services that expose JSON, but the page methods look handy.
Hello Dave,
Good post, especially that I fall in some of those mistakes like length required and Internet explorer XmlHttpRequest problem when I first produced my on demand loading sample using jQuery.Ajax.
Thank you for the tips
What about calling .ashx handlers using JQuery , i think it is lightweight and flexible than Page Methods.
I don’t think there’d be much difference in performance there.
I’d definitely be interested in seeing some testing between those two. IAsyncCallback too, for that matter.
hey,
is there any way to make “GET” work like this as well? i’ve been trying all morning but just get parsererror.
i can get it work with a readonly query but not with data parameters.
cheers.
If you’re using it with ASP.NET AJAX, the request has to be a POST, for security reasons.
you can use httpget=true in the scriptmethod attribute on a webmethod. just can’t seem to pass parameters to it….i guess you don’t really need it.
This was all working great for me, until today :(
Unfortunately, it all seems to fall down under Firefox 3, and I am having one heck of a time trying to find out why :(
(PS: Sorry about the double-post on the older blog entry, I was having trouble finding the correct one)
That’s odd. The code I posted still works for me in FireFox 3 (most of my original development and testing for these posts was done in FF3 betas too).
Are you getting an error at all? Try watching the request and response in FireBug.
No, I’m not getting any errors, and FireBug gives me absolutely nothing… No request headers, no response (headers or data), nothing. When I debug, the ReadyStateChanged event is fired with a status code of 0. FF 2 continues to work fine, as do Safari, Opera, and IE.
Obviously it’s time to extract this piece into a smaller repro case, cause I’m finding it hard to debug in the context of the larger application :(
Sometimes I wish I could go back and delete my comments, they are so embarrassing, haha.
After hours of searching, and reducing the problem to it’s very simplest components, and testing every permutation I could think of, I finally found the problem: Firebug itself, possibly in conjunction with (or because of) Aptana debugging extensions.
I had recently tried to start using Aptana Studio, and it required me to revert to an older (Aptana-customized) version of Firebug as well as add another Aptana-specific Firefox add-on, and apparently they are not fully compatible with FF3.
After removing those and “upgrading” Firebug to the latest version, everything is back to normal.
So let me apologize for wasting your time and to take this opportunity to thank you once again for the great info in the article!
@Takuan
No apologies needed here. I’m happy to know about this issue, now I don’t have to encounter it myself.
Thanks! :)
Firstly, thanks Dave after reading your original post on this subject, I’ve stopped using Script Manager and the ASP.NET AJAX framework completely.
I have since written a very simple function that replaces the jQuery ajax call. The function embodies each of the issues you raise in this post and supports GET & POST requests to both (JSON Enabled ASP.NET) Page Methods & Web Services.
An example of a call to the Page Method or Web Service is below.
Details can be found here: Briding ASP.NET & jQuery.
Great post - all common ‘gotchas’ - thanks!
I’m using jQuery with asp.net mvc - it’s magnificent :)
Hi Dave, what would be the easiest way to allow this to work cross-site (call a service from another site)?
I know it’s possible with JSONP, and that JQuery can handle JSONP.
What’s not clear is if there is any way in the 3.5 framework to easily implement it on the server.
Great articles by the way.
Best regards,
Lee
Hi, Lee.
As far as I know, there aren’t any built-in methods for generating JSONP. It shouldn’t be very difficult to roll your own though, using JavaScriptObjectSerializer.
Question. Does this work in ASP.NET 2.0 apps? I seem to have everythng working fine in the 3.5 apps I am using this in, but can’t seem to call a PageMethod in my 2.0 apps. Also I am using vb.net. Not sure if there are differences there either.
Thanks for the great post. I am having some trouble getting it to work in VN.NET though. And can’t fing an example of calling a page method with JQuery in VB.NET
I don’t think my problem is with .NET 2.0 since I have ASP.NET AJAX 1.0 installed. The problem seems to be trying to call a VB.NET Page Method because it works fine for me in C#. I must be missing something…
Imports System
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.HtmlControls
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Partial Class vbTest
Inherits System.Web.UI.Page
Public Function GetDate() As String
Return DateTime.Now.ToString()
End Function
End Class
This is what I have trying to reproduce the C# date example from the post in VB.NET. Any help would be greatly appreciated.
Thanks,
-Adam
Hi Adam,
You need to decorate your PageMethod with the
<WebMethod()>attribute to expose it as a web service.Rich
Hi,
I’ve created a jQuery plugin for easy communication with ASP.NET Ajax enabled Web Services and PageMethods.
Details can be found here.
Rich
Check out http://schotime.net/jMsAjax.aspx for a fully functional jQuery plugin (jMsAjax) that requires no external libraries except for jQuery.
It also passes Dates in and out of web methods and services.