ASMX and JSON – Common mistakes and misconceptions
AJAX, ASMX Mistakes and Misconceptions, ASP.NET By Dave Ward. Posted March 3, 2010Note: This post is part of a long-running series of posts covering the union of jQuery and ASP.NET: jQuery for the ASP.NET Developer.
Topics in this series range all the way from using jQuery to enhance UpdatePanels to using jQuery up to completely manage rendering and interaction in the browser with ASP.NET only acting as a backend API. If the post you're viewing now is something that interests you, be sure to check out the rest of the posts in this series.
While we were recording episode 5 of Mastering jQuery, I found myself running down a lengthy list of misconceptions and potential pitfalls when it comes to using ASMX services for AJAX callbacks. After years of fielding questions revolving around that topic, I suppose I’ve developed a decent handle on the issues most often encountered.
To preemptively surface some of that commonly requested information, I’m going to publish a series of relatively short posts, each describing one mistake or misconception that I’ve seen come up frequently.
To get started, I want to cover one of the most fundamental of these misconceptions: That ASMX services can’t return JSON.
Misconception: ASMX services are limited to XML
One of the most stubbornly persistent misconceptions about ASMX services is the rumor that they are limited to returning XML. With that notion mind, many developers understandably avoid them for client-side AJAX callbacks. When every byte counts, raw JSON is always preferable to the bloat of XML.
However, the introduction of ASP.NET AJAX removed that XML limitation.
In any ASP.NET 2.0+ AJAX enabled site, one of ASP.NET AJAX’s additions is something called the ScriptService. When a ScriptService is called in the correct manner, it automatically returns its result serialized as JSON instead of XML.
In fact, these ASMX ScriptServices even accept their parameters as JSON.
The ASP.NET AJAX “ScriptService”
If you’ve created an ASMX service in the past few years, you’ve probably seen this blurb at the beginning of the default template:
// To allow this Web Service to be called from script, // using ASP.NET AJAX, uncomment the following line. // [System.Web.Script.Services.ScriptService] public class WebService : System.Web.Services.WebService {
Since it never explicitly mentions JSON and implies a tight coupling with ASP.NET AJAX, it’s easy to understand why the ScriptService’s true power sometimes goes unnoticed. Thankfully, that attribute does much more than simply expose ASP.NET AJAX specific functionality.
In fact, the ScriptService attribute enables all of an ASMX service’s methods to respond with raw JSON if they are requested correctly. For example, these ScriptServices can easily send and receive JSON in conjunction with a third party library, without a ScriptManager or MicrosoftAjax.js anywhere to be seen.
Two simple requirements
As I alluded to earlier, the one stipulation is that these ScriptServices only return JSON serialized results if they are requested properly. Otherwise, even a service marked with the attribute will return XML instead of JSON. I can only assume that’s part of the reason for the misconception that ASMX services cannot respond with JSON.
Scott Guthrie has a great post on the specific requirements for coercing JSON out of ScriptServices. To summarize that, requests to the service methods must meet two requirements:
- Content-Type – The HTTP request must declare a content-type of application/json. This informs the ScriptService that it will receive its parameters as JSON and that it should respond in kind.
- HTTP Method – By default, the HTTP request must be a POST request. It is possible to circumvent this requirement, but it is advisable to stick with HTTP POST requests when dealing with JSON.
That’s it.
As long as those two requirements are satisfied, anything from low-level XMLHttpRequest code, to third-party libraries like jQuery, to ASP.NET AJAX itself can easily retrieve JSON serialized data from ASMX services.
Similar posts
What do you think?
I appreciate all of your comments, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums or Stack Overflow instead.
If you're replying to another comment, use the threading feature by clicking "Reply to this comment" before submitting your own.
2 Mentions Elsewhere
- The Morning Brew - Chris Alcock » The Morning Brew #553
- ASP.NET event kalender (icm ASP.NET) - 9lives - Games Forum



Since Microsoft is urging developers to move from ASMX to WCF, you might want to take a look at this: Creating a JSON-REST service using WCF
/ Anders
Edit: dead link redacted 2/2/2012; left the text so the comment still makes sense.
I think WCF is great in situations where you can take advantage of its strengths, like when you can use the tcpBinding mode. However, WCF’s complexity makes it hard to seriously consider for simple AJAX callback functionality where a better targeted, more mature solution already exists.
ASMX is by no means deprecated or obsolete, even in .NET 4. That’s actually one of the misconceptions I’m going to cover in this series.
Thanks for your posts about using web services with json. Your older posts really helped me get a handle on the requirements and now I use them anytime I need to do ajax. It’s really quick and easy once you understand those couple of gotchas.
Even Microsoft calls ASMX a “legacy technology”. Quote from MSDN Library : [...] a legacy technology. XML Web services and XML Web service clients should now be created using Windows Communication Foundation (WCF).
However, ASMX is what I started using when first moving into SOA. I do agree that it is a great option when you don’t need the extra goodies that WCF brings, such as the ability to respond to all HTTP verbs commonly associated with REST services – PUT, DELETE, GET, POST.
I don’t think many people know that ASMX is an option for hosting simple POST-based JSON-REST services, and I do like your post. :)
The interesting thing about that MSDN entry is that it may be legacy information itself (note that it’s a .NET 3.5 entry). Check out this newer MSDN entry about ASMX “ScriptServices” in .NET 4, which doesn’t carry that disclaimer anymore.
I think a good addition to this article would be a section on the cross domain issues. I’ve recently spent couple days coming across issue of setting Content-Type when requesting data from asmx services on a different domain. First: since its cross domain you cannot use XMLHttpRequest therefore you cannot set it header information in the Jquery. So the only way I found possible was to create an HttpModule which will add Content-Type header for requests coming to that service. It ended up being a lot of hassle to figure it out, and I was wondering what are your preferences on cross domain JSON services?
I agree.
I’m having a nightmare at the moment consuming my .asmx with jQuery cross browser :(
Probably the most fool-proof solution is using an intermediary proxy, like Sergey mentioned. I have a post on that here: http://encosia.com/use-asp-nets-httphandler-to-bridge-the-cross-domain-gap/
If you don’t need to support IE9 or earlier, check out CORS. If you configure IIS to respond with the correct HTTP headers on the site serving the ASMX, you can consume it cross-domain with a regular jQuery
$.ajax()call.I’ve added the recommended line(s) to my web config but still no joy…
This is the call I am trying to make:
$.ajax({
type: “POST”,
url: “http://wsp-sandbox6.co.uk/ReportInput.asmx/HelloWorld”,
data: “{‘name’ = ‘Bob’}”,
dataType: “json”,
contentType: “application/json; charset=utf-8″,
success: function (data) {
alert(‘yey’);
},
error: function (response) {
alert(‘yey1′);
}
});
Anything obviously wrong? If you get this working I’ll marry you!! This thing is driving me bonkers!
The data parameter needs to be valid JSON:
ASMX/JavaScriptSerializer will let you get away with the single quotes instead of double quotes, but not the equals sign instead of a colon.
$.ajax({
type: “POST”,
url: “http://wsp-sandbox6.co.uk/ReportInput.asmx/HelloWorld”,
data: ‘{“streetName”:”Bob”}’,
dataType: “json”,
contentType: “application/json; charset=utf-8″,
success: function (data) {
alert(‘yey’);
},
error: function (response) {
alert(‘yey1′);
}
});
Still no joy, just getting a 500 Internal Server Error….
At my wuits end with this, did that code work for you?
You’re getting close. The problem now is that you do have the correct Access-Control-Allow-Origin header to allow a CORS request, but you need a similar header that allows cross-domain requests that contain a Content-Type header. You can do that by adding another header:
Access-Control-Allow-Headers: Content-Type.Sorry for the stupid question but do you mean this in my web config?
If so I’ve just added that and still no joy :(
<add name="Access-Control-Allow-Headers" value="Content-Type" />I’m able to request your service now with this:
The response was:
I don’t understand…. not working for me but as you can see I have a very basic page?
Any ideas? Thanks for your help again!
I’m just getting:”NetworkError: 500 Internal Server Error – http://www.wsp-sandbox6.co.uk/ReportInput.asmx/HelloWorld“
By the error message, I’m assuming this is happening in Firefox? When I successfully requested your site with CORS, I was using Chrome.
One thing that might be causing your trouble is that your server isn’t responding to the OPTIONS “pre-flight” with an
Allowheader at all. My sites that are using CORS for ASMX do reply to OPTIONS with an Allow header of “OPTIONS, TRACE, GET, HEAD, POST”.Firefox may be considering the OPTIONS request a failure because the response indicates that OPTIONS isn’t allowed.
Yes it was in firefox, also just got the yey1 alert (so an error) but yes in chrome it did give me the yey alert(so it worked!)
Is the problem something that can be changed on the server then? I have access to it!
sorry meant to say also get the error in ie9.
This won’t work in IE9. Until IE10, IE only offers partial CORS support, which does not include the ability to pre-flight a request and obtain permission to send the Content-Type header.
OK thanks for all your help on this once again!!
If you know of any settings in iis or whatever that I can set to overcome this let me know.
Thanks again!!
I don’t know exactly what the difference is between our configurations, but my suggestion would be to try to figure out why my server responds to the OPTIONS pre-flight with this header that yours is missing:
Allow: OPTIONS, TRACE, GET, HEAD, POSTI’m not sure if this will help or not, but I put a sample ASMX service up on an IIS 7.5 server with no significant customization from stock settings. It responds to the OPTIONS pre-flight request, serves the two CORS headers we’ve discussed, and jQuery is able to complete a cross-domain AJAX request to it. Comparing how it responds to how yours does, what headers are present, etc may help you track down what your trouble is.
You can find that here (note the .net instead of .com): http://Encosia.net/WebService.asmx/HelloWorld.
They look quite different!!
I pointed the DNS for that domain to a new server a few hours ago. The change might not have resolved for you yet (you can test by trying to request WebService.asmx; it wouldn’t exist on the old IP). If you know how to add a hosts entry, you can force encosia.net to map to 68.71.136.100 on your machine to be sure your requests are hitting the right spot.
Well it’s working fine in terms of getting a response etc so if the service wasn’t on the old domain then I’m looking at the right place, right?
Here are the responses:
This is in firefox by the way.
Calling your webservice is working fine even in ff….
That looks correct now. I thought it was hitting the wrong one because I didn’t see the CORS headers coming from mine in your previous comment.
Let me know what you figure out to be the significant difference between yours and mine. I’m curious which exactly is thwarting Firefox.
When I last used a asmx ScriptService for returning JSON I noticed a severe bottleneck in the ASP.NET serialization process. It was taking forever to get the response back. I switched to generic http handlers and serialized the data with newtonsoft and gained a huge improvement with response time.
Are generic handlers known to be faster than ASMX? If you don’t need the coupling of ASP.NET AJAX and are using another library for AJAX calls are you better off with generic handlers? I would like to use ScriptMethods as opposed to generic handlers as I feel it makes my code cleaner but I don’t want to incur any unnecessary overhead.
I think it’s safe to say that HttpHandlers will always be faster than any higher level abstraction. That said, I’ve never had a performance problem with ScriptServices or JavaScriptSerializer that was related to the service layer itself.
The main reason I prefer ScriptServices to rolling my own HttpHandlers is how easily it lets me do things like this: http://encosia.com/2009/04/07/using-complex-types-to-make-calling-services-less-complex/
Amen to this. :)
Do you have any insite as to why Enums have to be passed as their numeric representation? Sadly this was a deal breaker for us.
If our clients are already calling our service with the URL: blah.com/service.asmx?Param1=EnumMember1, it would be great if we could tell them to just change the content type and they would be able to get back JSON. But they also need to change the URL to: blah.com/service.asmx?Param1=3.
And since the WSDL does not contain the numberic representation of the enum values, it is kind of a crap shoot since some of our enums are not numbered in order.
Happen to know of any work arounds for this?
To learn how the JavaScriptSerializer translates various types to JSON, take a look at this MSDN entry: http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer%28VS.100%29.aspx
The converter will attempt to automatically type convert input parameters. Using the System.Web.HttpCacheability enum, for example:
If you call that service with a string parameter like:
CacheSetting will be correctly set to the corresponding enum value.
I haven’t tried that with a QueryString parameter like you’re describing though. If you give it a try, I’d be interested to hear if it works for you that way or not.
That won’t work through HTTP Get. Don’t want to have existing HTTP Get clients change to HTTP Post just to get JSON data back.
Did you try it? I just tried hitting that test service with this URL:
TestService.asmx/SetCacheability?CacheSetting=NoCache
And it worked as desired.
Yeah, this is what we get for the example:
blah.com/service.asmx?Param1=EnumMember1
Do the enums and its members need any special attributes?
Sorry, I misunderstood part of what you’re after. The string to enum mapping does work, but you can’t mix QueryString parameters and JSON output.
When you set the request’s content-type to application/json, that’s describing the type of the request‘s data, not the response. ScriptServices just happen to automatically respond to a JSON input with JSON output. So, when you set that content-type, the service method only accepts input parameters as keys and values in a JSON string, not QueryString parameters.
Unfortunately, I don’t think there’s a way to coerce ScriptServices to take QueryString parameters and then return JSON results.
WCF or ASHX are better options if you need to send JSON in response to a GET. RESTful-ness aside, keep in mind that returning JSON via GET should only be used when the data requires absolutely no security considerations.
It is worth noting that (historically, anyway) there is a default cap on how much content can be returned via JSON. It can be reconfigured via a maxJsonLength attribute in your web.config. Microsoft mentions this in http://msdn.microsoft.com/en-us/library/bb763183.aspx.
Hi ,
I have implement jquery,Json,and asp.net WebSevice 2.0 using C# 2.0.
I have already use in web.config File
Further give error Message.
How can resolved it.
Error Message :-Request format is unrecognized for URL unexpectedly ending in.
#Start Error Message
Request format is unrecognized for URL unexpectedly ending in ‘/GetRecordTech’.
body {font-family:”Verdana”;font-weight:normal;font-size: .7em;color:black;}
p {font-family:”Verdana”;font-weight:normal;color:black;margin-top: -5px}
b {font-family:”Verdana”;font-weight:bold;color:black;margin-top: -5px}
H1 { font-family:”Verdana”;font-weight:normal;font-size:18pt;color:red }
H2 { font-family:”Verdana”;font-weight:normal;font-size:14pt;color:maroon }
pre {font-family:”Lucida Console”;font-size: .9em}
.marker {font-weight: bold; color: black;text-decoration: none;}
.version {color: gray;}
.error {margin-bottom: 10px;}
.expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }
…..
…
#End Error Message
Please help to me
Thanks & Regards
Alok Kumar Sharma
Is this error when you try to access it on VS Development Server or IIS?
Make sure you’ve got the ASP.NET AJAX Extensions v1.0 installed and the web.config updated for ASP.NET AJAX (specifically the HttpHandler change for *.asmx).
Thanks for the post, i just happened to run into this issue (well apparently not an issue) earlier today and made a mental note to figure this out sometime. And now i just stumble on your post :)
i do php.My client ex-vendor using asp.net.They said they create a web service for easy other developer.
My problem
1.Extjs doesn’t support soap request.
2.Output send using extjs return diff which are xml not soap response.
My conclusion,i make my customer php ->json ->extjs->adobe air.
Thanks for the wonderful series on asp.net + jquery.
I have successfully implemented Jquery ajax calls to the asmx web service for simple db interaction. Several problems were solved while doing it your way
1) simplicity of use
2) speed
3) data integrity
It’s a really clean solution that doesn’t involve ajax toolkit and extra work required to really understand what’s going on behind the scenes. Your gotchas:) really helped.
Thanks for the post, i just happened to run into this issue (well apparently not an issue) earlier today and made a mental note to figure this out sometime.
Thanks this is a great article!
Hello Sir,
I had go through your tutorial and I am very thankful to you that you have share this tutorial.
Sir, I am using vb .net web service. Actually, I don’t have knowledge of .net but learning through internet.
Actually, I am an android developer and I need to parse data through json parsing.
But, sir here I cant get json response through web service.
Here, I post my code. Please guide me.
_
_
Public Function GetPersonDetails(ByVal a As Integer, ByVal b As Integer) As Integer
Dim c As New Integer
c = a + b
Dim js As JavaScriptSerializer = New JavaScriptSerializer()
Dim sJSON As Integer = js.Serialize(c)
Return sJSON
End Function
Here, i have write simple method for addition.
Output I got is as follows:
8
Please tell me what should I have to do.
Thanks in advance.
The reason only
8is being returned there is because you’re only giving JavaScriptSerializer a value (without a key). Unfortunately, that’s not valid JSON and many JSON parsers will probably be unhappy if you use them to decode8.If
GetPersonDetailswere to return a more complex type as it’s result (like aPersonobject), it would be serialized as valid JSON with{"key":"value"}pairs as expected.If you’re starting from scratch with .NET and mainly need to set up an API that returns JSON for your mobile app, let me suggest using the newer ASP.NET Web API framework and C# instead of VB. There’s nothing wrong with VB, but 95+% of the .NET example code you’ll find online will be C# and C#’s syntax is much closer to Java’s, so using C# should be a lot easier for you coming from Android development.