Using jQuery to Consume ASP.NET JSON Web Services
AJAX, ASP.NET, JavaScript, UI, jQuery By Dave Ward on March 27th, 2008
In response to many of the articles here, I receive feedback asking how to achieve the same results without using ASP.NET AJAX. As much as I’m a fan of ASP.NET AJAX, I must agree that its JavaScript payload can certainly be a drawback in some situations.
My recent deferred content loading post is an excellent example of that. I was using jQuery for presentational effects, and using a ScriptManager to call a web service. Loading the JavaScript for both frameworks was a bit counterproductive, since the whole point was to improve initial load time.
In this post, I intend to correct that.
First, I’ll cover the two requirements necessary when calling an ASMX web service that’s being JSON serialized by the ASP.NET AJAX extensions. Then, I’ll show you how to do this with jQuery. Finally, I’ll update the deferred content loading example accordingly.
Additional security when calling JSON serialized services
A security feature of ASP.NET web services that are JSON serialized through the ASP.NET AJAX extensions is that they must be requested in a specific way. This is an important deterrent against your services being used in XSS attacks. Scott Guthrie has a great post providing detailed information on the particulars. It boils down to is two things:
- The request must be an HTTP POST request
- The request’s content-type must be: “application/json; charset=utf-8″
When you register and call a web service through ASP.NET AJAX’s ScriptManager, you may safely enjoy blissful ignorance of these requirements. The framework transparently handles everything for you.
However, if you want to use a third party AJAX framework to request the JSON serialized output, you may run into trouble due to these security features.
How to make jQuery jump through these hoops
The solution is a bit less intuitive than using the ScriptManager or what you would normally expect from jQuery. Using jQuery’s getJSON() would make sense, but it unfortunately meets neither of the above security criteria.
The most reliable way that I’ve found is to use jQuery.ajax() as follows:
$.ajax({ type: "POST", contentType: "application/json; charset=utf-8", url: "WebService.asmx/WebMethodName", data: "{}", dataType: "json" });
As you can see, the first parameters set the request type and content-type as required by the ASP.NET AJAX framework.
When making a read-only request, the empty data parameter is the key. For reasons unknown, jQuery does not properly set the specified content-type when there is no data included.
The “{}” data parameter represents an empty JSON object, which you can think of as the JSON equivalent of null. Supplying this parameter will convince jQuery to correctly send the content-type that we’ve supplied, while it will be safely ignored by the web service.
If you’d like to see a closer examination of why this particular syntax is used, you’ll be interested in 3 mistakes to avoid when using jQuery with ASP.NET AJAX.
Putting it all together
Now that we know how to call the web service, appropriately modifying the original example is easy. Here’s the new ASPX code:
<div id="Container"> <div id="RSSBlock"> <div id="RSSContent" class="loading"></div> </div> <div id="Content"> <p>Lorem ipsum dolor sit amet, consectetuer adipiscing...</p> </div> </div> <script type="text/javascript" src="jquery-1.2.3.min.js"></script> <script type="text/javascript" src="Default.js"></script>
Notice that I’ve placed the JavaScript references below the rest of the page’s content. Since browsers block while requesting, loading, and executing JavaScript, it makes sense to defer that until as late as possible. This will serve to further boost the page’s perceived performance.
Finally, the jQuery code to call the web service and appropriately handle its result:
$(document).ready(function() { $.ajax({ type: "POST", url: "RSSReader.asmx/GetRSSReader", data: "{}", contentType: "application/json; charset=utf-8", dataType: "json", success: function(msg) { // Hide the fake progress indicator graphic. $('#RSSContent').removeClass('loading'); // Insert the returned HTML into the <div>. $('#RSSContent').html(msg.d); } }); });
Conclusion: Is it worth it?
By using jQuery to call the web service directly, we’ve eliminated over 100 KB of JavaScript and three extra HTTP requests. The ASP.NET AJAX client side framework accounted for over half of the original example’s total download size, and those three extra HTTP requests unnecessarily delayed the progress indicator.
That may not sound like much, but it’s significant. When it comes to loading speed and responsiveness, users do not perceive changes linearly. Fractions of a second make the difference between a site that feels sluggish and one that appears responsive.
A word about web services
Web services are great tools that afford you substantial flexibility. It’s important not to overlook them.
You’ve no doubt seen many AJAX examples that involve using the XmlHttpRequest to request the output of a specially designed page, resulting in CSV or otherwise arbitrarily formatted data instead of HTML. For instance, I’ve noticed that a lot of the auto-complete plugins for jQuery expect this sort of kludge.
I believe that to be a short-sighted and counterproductive way to do things.
Web services have often been maligned in the past, due to the XML bloat associated with SOAP. However, JSON makes this drawback a thing of the past. JSON is very lightweight, making it ideal for structured AJAX communication. With the inefficiencies of SOAP neutralized, I think the power and flexibility of web services cannot be overstated.
For example, if I decide to move my sites from WebForms to MVC, there is a large amount of functionality encapsulated in web services that I won’t have to worry about recoding or redesigning. It’s a great feeling to have that flexibility and ease of reuse.
When used well, I think web services are to WebForms what object oriented programming was to procedural and functional programming.
Try it for yourself: download the source
The full example’s source code (ASP.NET 3.5 required):
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 - March 27 | Alvin Ashcraft's Morning Dew
- Reflective Perspective - Chris Alcock » The Morning Brew #61
- March 28th Links: ASP.NET, ASP.NET AJAX, ASP.NET MVC, Visual Studio, Silverlight, .NET « .NET Framework tips
- Enlaces de Marzo: ASP.NET, ASP.NET AJAX, ASP.NET MVC, Visual Studio, Silverlight, .NET « Thinking in .NET
- Wöchentliche Rundablage: WPF, Silverlight 2, ASP.NET MVC, .NET 3.5… | Code-Inside Blog
- Using jQuery to consume JSON Services « HSI Developer Blog
- Links do dia 28 de Março: ASP.NET, ASP.NET AJAX, ASP.NET MVC, Visual Studio, Silverlight, .NET - ScottGu's Blog em Português
- Eye On .NET - Hisham Elbreky
- Using jQuery & JSON with ASP.NET at KeithRousseau.com
- Using jQuery to Consume ASP.NET « vincenthome’s Software Development
- 3 mistakes to avoid when using jQuery with ASP.NET AJAX
- jQuery with ASP.NET Json Web Services : { null != Steve }

Comments
We had been thinking about doing this with some of the stuff at my work. We love jQuery, but at the same time we wanted to call out to .net web services or web methods. Have you tried to do this same setup with [WebMethod] and [ScriptMethod(ResponseFormat = ResponseFormat.Json)]? I’ve never looked at it, but I would imagine that these methods could be call in a similar fashion to web services.
I probably wasn’t clear in my last comment, I am talking about page methods in the code behind.
I haven’t tried it, but I think the request is similar and it would be doable. You would just point the request at Page.aspx/PageMethodName.
Thank you for that, it was pretty clear and your notes in the middle as well as comparison with ASP.NET AJAX style were very clear and useful
Great post! I’d be very interested to see about that page method + jQuery piece you and Justin are talking about.
Re: Page Methods. I tested it out, and you can definitely call them the exact same way.
I removed the ScriptManager and UpdatePanel from my Why UpdatePanels are Dangerous post, added jQuery, and used this code to call the page method:
It worked, just like the example above, replacing the JavaScript proxy generated by setting EnablePageMethods to true on the (now removed) ScriptManager.
Good idea, Justin. I hadn’t even thought to try that, myself.
Sweet. Glad that worked. It will certainly come in handy in the future.
How are the webmethods serialized into JSON? I notice you use msg.d. If you switch the datatype in the jquery called to text it reveals the json string {”d”:”…”} for the msg. Where is “d” specified?
The “d” is a function of how ASP.NET AJAX returns JSON serialized data. The “d” acts as a container object.
Hi.
What if I want to pass complex data(js object) into jQuery ajax call?
I haven’t had a chance to try that yet.
The way I’d suggest going about figuring it out would be watch the request in FireBug or Fiddler, using ASP.NET AJAX on the client. You’ll see what gets POSTed, then can replicate that in the jQuery call’s “data” parameter.
Great find Dave. I guess JQuery is more useful than I imagined.
hi Justin,
very good article indeed.
1 Question - would this approach work for image/binary data retrieval from REST style webservices ? I Mean can we set the dataType as binary or JPEG ?
Typically, for serving binary data like that, I’d suggest looking into an ASHX handler on the server side.
On the client side, you could asynchronously request new data through that handler by updating the src of an img tag (or whatever element you’re displaying the binary data in).
Dave, you are not alone. I also removed ScriptManager and UpdatePanel and used jQuery instead. Works like a charm. In production environment. The difference is that I retrieve data from HttpHandler.
2Anatoly: You can send any object which can be serialized to JSON (i.e. name-value pair combinations). After calling eval() on client side you work with result like it’s an object:
var data = eval(’(’ + result + ‘)’);
var msg = data.Result.Message;
As for binary, I ran into the following problem: it’s pretty normal that binary data goes with another content-type. Unfortunately, jQuery offers access to XHR (XMLHttpRequest object) and its getResponseHeader method in ‘complete’ event when ’success’ with data processing has already passed. Does anybody know the work around?
Thanks Igor
Dave, this looks good. One thing you probably would want to mention though is how to send JSON *to* the server as a parameters as well. jQuery doesn’t do JSON natively and MS Ajax requires some special ‘wrapped’ formatting.
You can do this by wrapping parameters into MS Ajax’s JSON format (outer class with parameters as properties) and using a JSON library like Crockford’s JSON2 library. In many cases this parameter passing gives more of a service feel to the application and would allow you to pass ‘complex’ types around with parameters directly received by the service or page methods.
Same approach also works with the new WCF REST services.
Hi Guys
I am trying an example similar to the one above but I am getting an invalid JSON primitive error. I have a local web service working fine and I’m attempting to retrieve a string from it. My code is not reaching the debug in the web service because it fails in the javascript beforehand with the error below.
{”Message”:”Invalid JSON primitive: origin.”,”StackTrace”:” at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializePrimitiveObject()\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize
(String input, Int32 depthLimit, JavaScriptSerializer serializer)\r\n at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit
)\r\n at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize[T](String input)\r\n at
System.Web.Script.Services.RestHandler.GetRawParamsFromPostRequest(HttpContext context, JavaScriptSerializer
serializer)\r\n at System.Web.Script.Services.RestHandler.GetRawParams(WebServiceMethodData methodData, HttpContext context)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext
context, WebServiceMethodData methodData)”,”ExceptionType”:”System.ArgumentException”}
===============================================================
here is my ajax code…
===============================================================
$.ajax({
type: “POST”,
data: “origin=” + $(”#origin”).val() + “&destination=” + $(”#destination”).val() + “depDate=” + $(”#depDate”).val() + “&retDate=” + $(”#retDate”).val(),
url: “/WebServices/KayakService.asmx/GetFlightSearchId”,
beforeSend: function(xhr) {
xhr.setRequestHeader(”Content-type”,
“application/json; charset=utf-8″);
},
dataType: “json”,
success: function(msg) {
searchId = msg;
alert(’Search ID = ‘ + searchId)
}
});
Has anyone ran into anything like this before?
I believe the problem is that your “data” isn’t proper JSON. As Rick mentioned above, you can use the JSON2 library to help automate that process.
Take a look at this page for more info: http://www.json.org/js.html
The library is linked at the bottom of that page.
In your particular example, try changing your data parameter to:
Hi Dave
Still getting the same error after making the suggested change, will try that json2 library out tho cheers.
Mart
Sussed it Dave - I just needed to escape everythin like this…
data: ‘{”origin”:”‘ + $(”#origin”).val() + ‘”,”destination”:”‘ + $(”#destination”).val() + ‘”,”depDate”:”‘ + $(”#depDate”).val() + ‘”,”retDate”:”‘ + $(”#retDate”).val() + ‘”,”sessionId”:”‘+ sessionId +’”}’,
Just realised, this only works in Firefox, it fails in IE7 every time. I can’t seem to find out the error either, IE7 must not like the JSON format perhaps?
The JSON formatting should be the same between browsers. Are you getting a JavaScript error from IE?
Hi Dave
I’m not getting a javascript error, the ajax call just fails with no message.
I narrowed the code down and produced a simplified version and I think that it is definitely the ‘data:’ line that causes the issue.
try your example again but add in a data: block to pass a simple param. It works in both IE7 and Firefox without the ‘data:’ line but as soon as you put it in, it only works on FireFox.
I simplified mine to accept 1 param which I put as
data: ‘{”name”,”dave”}’,
this was enough to make it only work on firefox.
Cheers
Mart
Hi Dave
Did you manage to suss this one out for me? It’s a proper showstopper at the minute.
Mart
Martin, I’ve been able to reproduce the problem here, and think I’ve cured it. What I believe I found to be the problem is a bit bizarre though, so I want to make sure I’m correct.
Could you email me the modified version that you’re using, which reproduces the issue?
Hi Dave
I’ve sent you a zipped sample project with everything narrowed right down.
Thanks a lot
Mart
It turns out that IE7’s XmlHttpRequest implements setRequestHeader as an appending function instead of a replacement.
Because jQuery does set the content-type on POST requests that have data, the content-type gets set to the default “application/x-www-form-urlencoded” initially. Then in IE7, setRequestHeader was adding “application/json; charset=utf-8″ to that instead of truly setting it. So, the content-type was incorrect for JSON serialization and the web service was returning XML instead of JSON.
Bottom line, replace this:
With this:
contentType: "application/json; charset=utf-8",Just keep in mind that you can only do this on calls that have POST data. If you’re making a read-only call, like in my example, you must still use the beforeSend method to set the content-type.
Dave! you’re an absolute star mate - nice one!
Mart :D
hey dave, just one detail that i didn’t realize before i started to mimic this was that the variable name on the web service and the json object key, have to be the same. i kept getting an error before i did this.
I’m having a trouble serializing a date.
Microsoft ASP.NET AJAX serialize DateTime objects using UTC format.
This is the format: \/Date(UTC TIME)\/.
For example \/Date(1208644401687)\/.
I’m trying to serialize a date using json2.js from http://www.json.org before passing it to the $.ajax call. This is the code:
var dat=”\\/Date(1208644401687)\\/”;
var myData={title:”hello”,data:dat};
var myDataSerialized = JSON.stringify(myData);
dat has a value of \/Date(1208644401687)\/ but when serialized it becomes \\/Date(1208644401687)\\/. I don’t understand why json serializer adds 2 backslash. It seems there’s no way to serialize a date in the correct format. Any suggestion?
I’m having the same problem, however this problem only exists in .net 2.0 because 3.5 seems to accept the “2008-06-26T10:20:06Z” format which means you can just use the JSON.stringify on new Date() and it will work fine, however not in 2.0.
I’m trying to figure it out. Hopefully i will get somewhere.
Hey, Dave, greeeeat post! Also Rick has some good points and great article on his site. Keep up good work guys, it really help me.
Dave and crew… I wanna ask your opinion on some stuff. My imagination has ran wild since the birth of jQuery and ajax. At the moment I want to recode all my asp.net postback work into an ajax / jquery style framework.
The reason i wanna do this is to increase the WOW factor of websites. No longer do people need to wait for that predictable flicker while they are presented with the data they want.
With lazy load of API javascript code and the like we have a platform to do what the hell we want to??? or am i much mistaken? - The possibilities in my head are endless at the minute. Enough to make me no longer need the code behind model of ASP.NET or even the AJAX part of ASP.NET for that matter (overbloat???).
Someone please bring me back down to earth before i get carried away….
Marv
I believe websites will completely change their underlying technology over the next few years, in an attempt to overcome the standard boundaries of web dev and this will spill into what everyone knows today as TV……..
Mark my words.
The Dannster (write this down)…..
I say: Get carried away!
The one thing I would suggest is waiting on the ASP.NET MVC framework to be fully released. If you’re going to start rewriting pages anyway, rewriting them MVC is going to be the way to go.
Once you get your head wrapped around the MVC methodology, it’s a thing of beauty. There’s no going back. MVC meshes very well with the idea of using RESTful web service calls to provide a rich client-side interface to your app.
Hi, I’m getting the same error message Martin was reporting. What was the final resolution? Parameterless methods work, I only hit a wall with parameters. Any help would be much appreciated.
I believe jQuery requires a string argument for “data”. Try this instead:
data: "{'test':'jim'}",It’s the web service itself that will take the JSON string and parse it out, on the server side.
Cracked it. Data needed to be passed as a string.
Great post, thanks. Rich
hi there,
i have been postponing my Jquery Json learning for too long.
but i am tackling it now, no more excuses.
I also have to mention, i still working on the net 2.0
could you give us some pointers on how to get this one to work in 2.
i understand the whole, although been reluctnt to swap to ajax development for too long and after review your webconfig i get a bit lost.
any pointers on where to get the concrete info for me to know how to enable json with asp.net 2.0 in my webconfig.
thanks,
Dave
This documentation will help you get your web.config set up for using ASP.NET AJAX with 2.0:
http://www.asp.net/ajax/documentation/live/ConfiguringASPNETAJAX.aspx
I’m trying to get this to work while passing in HTML code as a string. The reason is the following: I’m attempting to store a block of html code in a database that can be modified by the user throughout the site without doing a full page postback. using javascript seemed to be the best solution, however, it fails with an invalid formatted string.
This is the data: val
Any ideas on how i would successfully pass this param through?
The double quotes in your HTML string are breaking the JSON literal. Look into HTML encoding in JavaScript, and you’ll find some techniques to handle that.
FIXED! Thanks so much!
When calling asp.net webservices with jQuery, would you need to do something special to be able to access Session data or user specific data, like membership, account properties etc.?
In order to access the session from a webservice, you need to amend the WebMethod take like so:
using jQuery resolves some problems and eases the process somehow