ASP.NET web services mistake: manual JSON serialization
ASMX Mistakes and Misconceptions, ASP.NET By Dave Ward. Updated April 14, 2011Note: 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.
If you’ve spent much time working with the .NET platform, ASP.NET’s simple, convention-based approach to exposing JSON endpoints seems just about too good to be true. After years of fiddling with manual settings in XML configuration files, it’s understandable to assume that working with JSON in ASP.NET would require a similar rigmarole, yet it does not.
Unfortunately, this unexpected ease-of-use isn’t obvious if you don’t already know about it, which has led some developers to build needlessly complicated solutions to problems that don’t actually exist. In this post, I want to point out a few ways not to approach JSON in ASP.NET and then show you a couple examples of leveraging the frame work to do it “right”.
A couple examples of what NOT to do
To show you exactly what I’m talking about, let’s start by looking at a few concrete examples of ways that you should not handle sending and receiving JSON in your ASP.NET services.
For all the examples, we’re going to be trying to send and/or receive instances of this Person class:
public class Person { public string FirstName { get; set; } public string LastName { get; set; } }
Once you progress beyond simple scalar types, sending objects (and collections of them) back and forth is a pretty logical next step, and that’s also the point where this manual serialization trouble seems to begin. So, working with this simple Person class should serve as a realistic example, without being overly complex.
Manual serialization, using JavaScriptSerializer
The most common variant of this mistake that I’ve seen is using JavaScriptSerializer to manually build a JSON string and then returning that string as the result of a service method. For example, if you didn’t know better, you might do this to return an instance of the Person class:
[ScriptService] public class PersonService : WebService { [WebMethod] public string GetDave() { Person dave = new Person(); dave.FirstName = Dave; dave.LastName = Ward; JavaScriptSerializer jss = new JavaScriptSerializer(); // Results in {"FirstName":"Dave","LastName":"Ward"} string json = jss.Serialize<Person>(dave); return json; } }
This may look sensible enough on the surface. After all, the json variable does end up containing a nicely serialized JSON string, which seems to be what we want. However, you should not do this.
What actually happens
Part of the beauty of using ASP.NET’s JSON-enabled services is that you rarely have to think much about the translation between JSON on the client-side and .NET objects on the server-side. When requested with the proper incantations, ASP.NET automatically JSON serializes your service methods’ responses, even if their result is an object or collection of objects.
Unfortunately, that automatic translation also makes it easy to end up with doubly-serialized responses if you aren’t aware that ASP.NET is already handling the serialization for you, which is exactly what would happen in the preceding example. The end result is that the Person object is serialized twice before it gets back to the browser – once as part of the method’s imperative code and then a second time by convention.
In other words, it’s understandable to expect the previous code example would return this response:
{"FirstName":"Dave","LastName":"Ward"}
But, what it actually returns is this:
// All the quotes in the manually generated JSON must be escaped in // the second pass, hence all the backslashes. {"d":"{\"FirstName\":\"Dave\",\"LastName\":\"Ward\"}"}
What a mess. That’s probably not what you had in mind, is it?
Using DataContractJsonSerializer or Json.NET is no better
This may seem obvious, but I want to point out that using a different manual serialization tool, like WCF’s DataContractJsonSerializer or Json.NET, in place of JavaScriptSerializer above does not remedy the underlying problem. I only mention it because I’ve seen those variations of the mistake floating around too.
If anything, in the case of DataContractJsonSerializer, it’s even worse. DCJS’ handling of Dictionary collections and Enums makes life unnecessarily tedious at times, and the code to manually invoke it is even more verbose than that for JavaScriptSerializer.
The impact this mistake has on the client-side
If it weren’t bad enough to add extra computational overhead on the server-side, cruft up the response with escaping backslashes, and increase the size of the JSON payload over the wire, this mistake carries a penalty on the client-side too.
Most JavaScript frameworks automatically deserialize JSON responses, but (rightfully) only expect one level of JSON serialization. That means that the standard functionality provided by most libraries will only unwrap one level of the doubly serialized stack of JSON produced by the previous example.
So, even after the response comes back and your framework has deserialized it once, you’ll still need to deserialize it a second time to finally extract a usable JavaScript object if you’ve made the mistake of manually serializing. For example, this is code you might see to mitigate that in jQuery:
$.ajax({ type: 'POST', dataType: 'json', contentType: 'application/json', url: 'PersonService.asmx/GetDave', data: '{}', success: function(response) { // At this point, response is a *string* containing the // manually generated JSON, and must be deserialized again. var person; // This is a very common way of handling // the second round of JSON deserialization: person = eval('(' + response + ')'); // You'll also see this approach, which // uses browser-native JSON handling: person = JSON.parse(response); // Using a framework's built-in helper // method is another common fix: person = $.parseJSON(person); } });
Regardless of which approach is used, if you see code like this running after the framework has already processed a response, it’s a pretty good indication that something is wrong. Not only is this more complicated and verbose than it needs to be, but it adds additional overhead on the client-side for absolutely no valid reason.
Flipping the script (and the JSON)
Redundant JSON serialization on responses is definitely one of the most common variations of this problem I’ve seen, but the inverse of that mistake also seems to be an alluring pitfall. Far too often, I’ve seen service methods that accept a single JSON string as their input parameter and then manually parse several intended inputs from that.
Something like this to accept a Person object form the client-side and save it on the server-side, for example:
[ScriptService] public class PersonService : WebService { [WebMethod] public void SavePerson(string PersonToSave) { JavaScriptSerializer jss = new JavaScriptSerializer(); Person p = jss.Deserialize<Person>(PersonToSave); p.Save(); } }
Just as ASP.NET automatically JSON serializes responses on its JSON-friendly services, it also expects that the input parameters will be in JSON format and automatically deserializes those on the way in. So, in reverse order, the approach above makes a mistake similar to the ones shown earlier.
To make this work, we’d need to pass in JSON that looks something like this, obfuscating the actually desired input parameters inside a single, doubly-serialized string parameter.
{"PersonToSave":"{\"FirstName\":\"Dave\",\"LastName\":\"Ward\"}"}
Through the convenience of JSON.stringify(), it’s not even terribly hard to stumble onto a process for cobbling that double-JSON structure together on the client-side and making this approach work. I strongly recommend against it though. Even if the double-JSON didn’t carry extra overhead in several aspects, having a single input parameter of type string on this method is misleading. A year from now, will anyone realize what type of parameter that method accepts without looking down into the manual parsing code? Probably not.
Doing it right
Briefly, here are what I suggest as better ways to handle passing our Person object in and out of ASP.NET services.
Returning an object
Returning a .NET object from ASP.NET services is incredibly easy. If you let go and just trust the service to handle JSON translation for you, “it just works”:
[ScriptService] public class PersonService : WebService { [WebMethod] public Person GetDave() { Person dave = new Person(); dave.FirstName = Dave; dave.LastName = Ward; // So easy! return dave; } }
As long as you call that service method through a ScriptManager’s service proxy or using the correct parameters when using a library like jQuery, ASP.NET will automatically serialize the Person object and return it as raw, unencumbered JSON.
Accepting an object from the client-side
Accepting a Person object from the client-side works identically, in reverse. ASP.NET does a great job of matching JSON-serialized request parameters to .NET’s types, collections, and even your own custom objects.
For example this is how you could accept a Person object, which would even then allow you to call that object’s custom methods:
[ScriptService] public class PersonService : WebService { [WebMethod] public void SavePerson(Person PersonToSave) { // No, really, that's it (assuming Person has a Save() method). PersonToSave.Save(); } }
For more information about how to implement this on both server- and client-side, I recommend reading my old, but still-relevant, post about using objects to simplify calling ASP.NET services.
My request to you
I don’t know where the manual [de]serialization approach is coming from, but it seems to be gaining traction lately based on what I’ve seen on Stack Overflow and the ASP.NET forums. I must assume there are tutorials out there with sample code showing that approach, or valid approaches within ASHX handlers are being mistaken for the proper solution across the board.
Whatever the source, I can only find and correct a fraction of the postings and questions containing this mistake myself. If you notice an instance of these mistakes that has not been corrected, please take a moment and point them toward this post.
Together, hopefully we can stop the spread of this particular mistake.
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
- ASP.NET, AJAX i JSON « Asp.net « Web Development « Pure Development Blog
- Google Charts, ASP.NET, jQuery, AJAX – Quick & Easy » Girl From Out of This World



Great post. I think one reason we (I included) instinctively lean towards manual serialization is because we don’t expect there to be a magic feature that handles this for us.
Another great post Dave. I’ve been trying to push for this with the guys at the office since I saw your Tekpub series and saw how easy it was. Although I never thought to consider it could even parse that JSON back down to entities. Now I’m wondering how easy that would be to tie into something like jquery data link.
Great post. In fact I am finding your blog is essential reading in general.
I am only just beginning to use JSON with Client Side Templating for Views and I realise I’m well behind the curve. Would you still recommend using the DataView technique forclient-side templating for ASP.NET 4, which you demonstrated in old post of yours?:
http://encosia.com/2008/07/23/sneak-peak-aspnet-ajax-4-client-side-templating/
I do still recommend using the same general approach, combining JSON data and client-side templates, but don’t use the DataView. It has been discontinued (before ever officially being released even). Instead, I recommend using jQuery Templates for that functionality going forward.
Just beware of the System.DateTime automatic deserialization.
If your CLR Person class would have an Age property of type System.DateTime, and the person dto would have same field with javascript Date, the automatic deserialization might produce wrong value (As far as I remember one day earlier than the expected).
In order to fix it, your person dto should call the toString() method of the Age field right before posting the data to the server.
It appears the method in your last code example is mis-named. It’s saving a person, yet called GetDave(). Great post otherwise. Really clearly states this common problem!
That’s a good point. I renamed it to make more sense.
Good article. I’ve learned to trust the webservice to spit back valid JSON when I’m sure to send my request as JSON. I’m a big jQuery advocate. The only thing to consider is that in your example of returning a Person… it’ll be contained within “d”
Thank God for the great community of developers out there.
2 things I’ve run into on this which may or may not be out of scope here…
1) The big “Do Not” here seems to be predicated on web service usage. I had a block of JSON that I wanted cached on the client, so I made it a web page that the client would GET (instead of POST). Is there a clever class-attribute for that? (Lacking it, I didn’t run into any escaping issues but did muck about with a MemoryStream and Encoding.UTF8.GetString.)
2) On a tangent, if you’re throwing around huge blocks of JSON (that you might want your clients to cache, for example), you may run past the default max-length of JSON. I don’t know whether or not this impacts the attribute-serialized methods, but I expect it does — it certainly bit the DataContractJsonSerializer. You can alter the default by setting //configuration/system.web.extensions/scripting/webServices/jasonSerialization[@maxJsonLength] to a new (huge) quantity of bytes in your web.config file.
The way I would probably tackle #1 is to use localStorage for the caching (with a compatibility layer like store.js for older browsers). That way, you have more explicit control over the caching, whereas browsers are likely to push a large GET response out of cache quickly.
If you do need to use a customized endpoint like that, HttpHandlers are the way to go instead of pages. Creating an ASHX handler is just about as easy as an ASPX page, but avoids the overhead of creating a Page instance and running through the page lifecycle.
Hats off Dave, you pointed the right point in right time.
This will boost our usage of jQuery in ASP.Net developments.
What about anonymous types? What if I didn’t want to return an entire person object or had a bunch of classes I wanted to mash together so that the response was more meaningful.
If you use return type
object(and probablydynamic, as well), you can return anonymous types from these services. For example:Wow! I can’t believe I’ve never tried that before.. thanks for the heads up!
When I try this, I get: “cannot be serialized because it does not have a parameterless constructor”. See http://stackoverflow.com/questions/267724/why-xml-serializable-class-need-a-parameterless-constructor
Thank you very much for your article. I was stuck in this kind of problem and trying everything to escape with no luck. Have a great day…
Wow … to be honest I am not surprised people do this. I still see people doing their own serliazation/deserialization of objects with XML.
The framework does it for you … so let it. It’s like programmers have to make it more complicated than it really is.
As one of the victims of such bad advice, I thank you, sir.
My code is much cleaner now and Firebug can properly parse the JSON responses, which is a GREAT help.
One question, though – I am trying to return SQL results as JSON via a WebService and when I return the results as a DataTable, The serializer throws circular reference errors. When I manually convert the DataTable to List it is OK but I can’t help feeling that I’m still doing too much:
So for instance internally to the WebService I would use:
Am I still jumping through too many hoops?
Do _not_ return a datatable from a webservice. Even worse, is a dataset.
Return a collection of POCO objects as you are.
Here is a link about returning datatables and trouble serializing them.
http://support.microsoft.com/kb/306134
POCO? Yo!
Is there a way to tell ASP.NET not to add the “__type” parameter when serializing to JSON ?
If I have a class Country, with properties Code and Name, i get the following response:
{“d”:[{"__type":"SBAEvolveWebService.Models.Country","Code":"AUS","Name":"Austria"}]}.
I’m using jQuery to retrieve the data so I don’t need the type as it only increases the size of the response (I guess the “__type” is used by ASP.NET’s ScriptManager)
In this case the size of the response is increased with more than 50% which defeats the purpose of the optimization. If I stick with manual serialization using JavaScriptSerializer there will be extra computational overhead on the server-side, but in my case it is better than having more data to download as I’m doing mobile development.
I would like to have automatic serialization but without the unnecessary data. Is this possible ? Thanks
Keep in mind that HTTP compression (i.e. gzip or deflate) will tokenize the __type string and it will have much less effective impact on the response size than it seems.
That said, one way I’ve eliminated it in the past is to return an anonymous type:
That tends to get unwieldy pretty quickly, so I’ve only used it when excluding __type is absolutely necessary, but is one way to control what’s returned.
Thanks for the suggestion, but it turns out that if you set the constructor of the class other than “public”, ASP.NET doesn’t include the __type.
I’ve set the constructor for my Country class as: internal Country() {} and it works! :). Found the answer on StackOverflow:
http://stackoverflow.com/questions/627356/how-to-not-serialize-the-type-property-on-json-objects
That’s good to know. Thanks for following up here with that.
What about returning an array of those objects? Any help on how to go about doing that? I’ve been looking everywhere and it all seems to point back to manual serialization.
Thanks!
You can return T[] or List the same way that you would a single object of the same type. For example:
That will return a JSON array that looks like this:
I agree, but disagree.
A good example is with MVC3. By default, it uses the JavaScriptSerializer. What if I want to control what NAME are used for name/value pairs? What if I want NULL properties to NOT be serialized?
Your only choice (that I’m aware of) is to inherit from the JsonResult and create your own that uses DataContractJsonSerializer. From there, you are then able to use the DataName attribute and its options as well as the IgnoreDataMember attribute to control how your Json is serialized.
With no way to tell the framework WHICH serializer you want it to use in any given case, especially with MVC3, I see no other option but to serializer manually.
Here is an example of a simple Node object I use to pass to jsTree, which will not work if serialized by JavaScriptSerializer/JsonResult:
This post isn’t really targeted at MVC, where you have more control over what you send back. Sending back manually serialized JSON as a ContentResult wouldn’t incur the double-serialization penalty that I’m describing here, of course. In ASMX/WCF/PageMethods, you don’t have that option. You either get XML or JSON, and if you choose JSON then you need to use the built-in serialization.
If you do choose to use DataContractJsonSerializer, watch out for how it handles Dictionaries.
I’ve had good success in MVC using a separate DTO/ViewModel and AutoMapper to project the more complex domain object into a DTO that represents just what I need to send the client-side. Using LINQ to select out an anonymous type and returning that through Json() works nicely in these situations too.
Thanks for clarifying, Dave. The approach I’m using with MVC seemed pretty valid to me. The DataContractJsonSerializer is a bit more palatable than LINQ anon types since it would require some recursion (I think) to build out List with anonymous types in LINQ otherwise.
It’s funny that you mention DTO/ViewModel and AutoMapper. The “Node” object I described is actually a ViewModel that is being populated from a DTO that I built from business layer entities using AutoMapper.. :-) Such a tangled web we weave.. AutoMapper is one of the coolest things I have pulled down from NuGet. Without it, trying to apply POCO to abstract away from these heavy middle-tier entities I have to utilize in my repositories and service tier would be a total hassle.
Hi Dave,
great post! Just one JavaScript / jQuery question: When I get this reply back:
{“FirstName”:”Dave”,”LastName”:”Ward”}
how could I process it in the browser then? Let’s say I want to write the reply into textboxes ‘FirstName’ and ‘Lastname’. How could that be done?
If you’re making the request with jQuery (or most any library with AJAX support), that JSON will be automatically converted to a proper JavaScript object before you need to work with it. So, assuming you had a couple of textboxes with IDs
FirstNameandLastNameand a service returning the JSON in your comment, you could fill those textboxes like this:More info on the
.d, if you haven’t run into it before: http://encosia.com/a-breaking-change-between-versions-of-aspnet-ajax/If I serialize object (dataTable), I get json string as I won’t.
For example:
{“userList”:[{"UserId":1,"UserName":"J1"},{"UserId":2,"UserName":"J2"}....]}
I have sql paging so I always returns only one page of data.
In front of this userList I would like to have also metaData, with number of all rows, all sum, …., something like:
{“metaData”:{“counter”:5, “sum”: 1000 }, “userList”:[{"UserId":1,"UserName":"J1"},{"UserId":2,"UserName":"J2"}....]}
So, how can I include also this data into json string, any example?
br, Simon
You can create a transfer object with that structure, like:
And then build an instance of that object out with your DataTable and metadata, and return the whole thing as your result.
Or, assuming you’re using .NET 3.5 or higher, you can also use an anonymous object to return that in a more ad-hoc manner within the method itself:
Thank you.
I tried also this approach. I have dataReader and I compose json string into stringBuilder(_Invoice) and at the end i response it, like this:
I guess, this takes less resources.
I have just one more question.
Which function can I use to parse some string into json string?
I have to replace quotations, backslash and similar…
I found this but I’m not sure if this is the right way:
http://www.aspcode.net/C-encode-a-string-for-JSON-JavaScript.aspx
thank you,
Simon
Hey, can you actually serialize an anonymous type?
Tried it in a WCF and an ASMX service and it doesn’t work. Google Search tells me that I can’t do so too.
I don’t know about WCF, but returning anonymous types works in ASMX ScriptServices and ASPX page methods as long as you use a compatible return type. For example:
object,dynamic, andIEnumerableare the types that I’ve used to return anonymous types in the past and can confirm do work.Well I tried an ASMX service again and this is what I ended up with…
That trace indicates that it was trying to serialize the object as XML, not JSON. Serializing an anonymous type only works when you’re using JSON.
Hey! Sorry for the delay.
I followed your other article on how to get a JSON response from ASMX services and got it working!
But for some reason the same doesn’t work in WCF Services, any idea why?
It should work with WCF too if you use AspNetCompatibilityRequirements. With that attribute, WCF works somewhat similarly to ASMX ScriptServices (just with more config hassle and not quite as nice a [de]serializer).
Messed around with ASMX ScriptServices a bit and yeah, it’s much simpler and suits my requirements.
Anyways, awesome articles this and the other one are! Keep blogging!
Dave
Great Post – this took me a while just to get any JSON ASPX WebMethods to be read from my ajax calls –
now that this is working I have another issue you might be able to help with.
I am getting an object back that ends up looking like
data.EVS[0].FirstName, data.EVS[1].FirstName, ….. from a List(of EVS) I am using.
when I try to use the $.each(data.EVS,function(index,item){….}); I am getting
unable to get the value of property ’0′.
I am assuming it is becaues of the List and how it is getting objectized in JS.
Any thoughts?
One thing to watch out for is that your data will come back wrapped in a .d object, unless you’re using ASP.NET 2.0. So, you’d probably need to reference that like
data.d.EVS.To iterate over a collection of items, you can use a simple for-loop similar to what you’d use on the server-side (assuming C#):
Does that help?
Thanks Dave – that does help – I had already implemented it that way , and yes – it is coming over wrapped in the .d – just wanted to make sure I wasnt loosing it -
This was a great post and has helped me out greatly –
I am not using a WebService , but a WebMethod in an ASPX page – not sure why , just have seen it that way
Creating a class to manage the data seems to be working great – for what ever reason I couldnt get a normal text stream out using a JSON format to work – spent hours trying to get it to fly – validated the returned string was a valid JSON format – still nothing …. oh well – thanks!
Hi, Dave.
After i read your post that helpful for me, i have some questions and hope you could answer them. First of all, Can i put WebMethod outside Web Services class ? Jquery AJAX and JSON play key roles in my application, following your example above, i’ll create many Web Services class for every table in database. Secondly, are there any error when i return POCO object generated from Entities Data Model without serializing ?
No, you can’t. You might want to look into oData as an alternative to manually creating services if all you’re doing is exposing EF data.
Third potion that i want to mention here is there some error when i tried to serialize POCO Object in webmethods are placed in web page For Example : Self referencing loop or cyclic references because relationship, i mean association between entities or tables. Whether WebServices can return POCO Object to JQuery AJAX and receive JSON as POCO Object without any error ? and How to deserialize JSON parameter sent from Jquery AJAX to web services ?
Thanks in advance !
Have a nice day !
Sorry for my bad english writing.
Hi, Dave
I’m getting error when using webservice “Only Web services with a [ScriptService] attribute on the class definition can be called from script” . Any ideas to sovlve it ?
You need to use a web service with the [ScriptService] attribute. That attribute allows it to “speak” JSON.
thanks, i solved.
I have a webservice that returns XMlDocument objects. When it returns JSON it is formatted like this {“d”:[[[[]],[[]],[[]],[[]],[[]]]]}. Do you have to use custom objects with defined public properties or is there a way to convert the XML to JSON? I ask because I have multiple clients consuming the XML and want to build a JSON feed as well.
I’d probably try to get at the underlying data before returning it through as JSON – preferably, using the same code to generate both the XML and JSON.
Alternatively, you could pull the values out of the XML with a bit of LINQ to XML (as in this example) and then return the resulting POCO for ASP.NET to automatically serialize.
Thank you. I will investigate. I’ve been playing around with Newtonsoft JSON.NET to convert the xml to JSON, but I’m running in to the double encoding issue you brought up. I will look at making my own POCO response.
hi,
i’m doing manual json serialization at one point in my page:
one of my pages is storing JSON in a hidden input, so i don’t have to make an additional request to a service or an action method that is returning JSON.
i need the data in JSON because my page’s script is using knockout.js and it uses it to populate various form inputs (ko.mapping).
actually i really would like to get rid of it. there is actually another problem with it. because i will have to parse the json or the properties of my objects for the MS DateTime /Date()/.
any suggestions?
Using JavaScriptSerializer to embed a bit of JSON in the page for quicker initial display is fine. This post is only about doing manual serialization in ASP.NET web services, where the framework automatically does that work for you regardless.
There aren’t any perfect solutions to the JSON date problem. The underlying issue is that JavaScript simply does not have a date/time literal. So, where you can express a string, number, or boolean easily in an object literal (and consequently in JSON), that isn’t as easy for dates. Hence, you see solutions like Microsoft’s /Date()/ being used to work around that deficiency.
Personally, I send DateTime.ToShortDateString() whenever possible. If the date is only being used for display purposes, then that ToString() representation is what you’re ultimately going to convert the date into on the client-side anyway. So, sending that string instead saves the hassle of dealing with the lack of a date literal in JavaScript.
Thank you Dave Ward, its really amazing article.
Dave is Batman
I don’t get it, I let asp.net webservice to handle the serialize, but the result I got is like, I am not sure if you indicated that you can solve this problem without using the manual serialization, but in my case, I don’t use manual serialization, why I get result like below?
{“d”:”{\”FirstName\”:\”Dave\”,\”LastName\”:\”Ward\”}”}
What you’re seeing there is the result of returning a JSON string as the string return value of the service, like:
Instead, you can just do this:
Hmm, but that didn’t get that result.
So my asmx looks like this
then I did the call below
In fiddler, I see result like
HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Wed, 07 Dec 2011 22:29:41 GMT
Content-Length: 114
{“d”:[{"__type":"Device","name":"forntdoor","address":"B2"},{"__type":"Device","name":"backdoor","address":"B4"}]}
Any idea what was wrong?
That JSON is correct now. The property names and any string values should be quoted to be valid JSON, but notice that they’re no longer part of one big string with escaped internal quotes now. In your success handler, you should be able to drill right into the data with something like
console.log(data.d[0].Device), where you couldn’t before without a second parse or eval.I thought in your article you said “What a mess. That’s probably not what you had in mind, is it?”, which should mean that there is a right way to scripe out the “d:”.
The
.disn’t the part that’s a mess there. It’s the double-serialization.That
.dis protecting against a potential CSRF-based vulnerability in your case since you’re returning an array as the top level object.Im trying to return code like this (can be found here: http://layar.pbworks.com/w/page/28473583/GetPOIs-Request%20and%20Response%20Examples):
{“hotspots”: [{
"id": "test_1",
"anchor": { "geolocation": { "lat": 52.3729, "lon": 4.93 } },
"text": {
"title": "The Layar Office",
"description": "The Location of the Layar Office",
"footnote": "Powered by Layar" },
"imageURL": "http:\/\/custom.layar.nl\/layarimage.jpeg",
}],
“layer”: “snowy4″,
“errorString”: “ok”,
“errorCode”: 0
}
But as you can see its a bit more complex structure than the Person class in your example. How would I be able to return code like that? What should I do in my class definition?
That data would look something like this on the server side:
Wow, thats a fast response :-D
I added the class like you mentioned but now the service is throwing an error:
The server encountered an error processing the request. The exception message is ‘Object reference not set to an instance of an object.’. See server logs for more details. The exception stack trace is:
Here’s my current code, I hope you can see why the error is now occuring while it wasnt previously with the other class:
**** RestServiceImpl.vb
Imports System.ServiceModel Imports System.ServiceModel.Web Imports System.IO Imports System.ServiceModel.Activation Imports System.Web.Script.Serialization Imports System.Collections.Generic Namespace RestService Public Class Hotspot Public Property id() As String Get Return m_id End Get Set(value As String) m_id = Value End Set End Property Private m_id As String Public Property anchor() As String Get Return m_anchor End Get Set(value As String) m_anchor = Value End Set End Property Private m_anchor As String ' etc End Class Public Class PointsOfInterest Public Property hotspots() As List(Of Hotspot) Get Return m_hotspots End Get Set(value As List(Of Hotspot)) m_hotspots = Value End Set End Property Private m_hotspots As List(Of Hotspot) Public Property layer() As String Get Return m_layer End Get Set(value As String) m_layer = Value End Set End Property Private m_layer As String Public Property errorString() As String Get Return m_errorString End Get Set(value As String) m_errorString = Value End Set End Property Private m_errorString As String Public Property errorCode() As Integer Get Return m_errorCode End Get Set(value As Integer) m_errorCode = Value End Set End Property Private m_errorCode As Integer End Class Public Class Employee Public Property Id() As String Get Return m_Id End Get Set(value As String) m_Id = Value End Set End Property Private m_Id As String Public Property FirstName() As String Get Return m_FirstName End Get Set(value As String) m_FirstName = Value End Set End Property Private m_FirstName As String Public Property LastName() As String Get Return m_LastName End Get Set(value As String) m_LastName = Value End Set End Property Private m_LastName As String End Class _ _ Public Class RestServiceImpl Implements IRestServiceImpl Public Function JSONData(ByVal lat As String, ByVal lng As String, ByVal d As String, ByVal cat As String) As PointsOfInterest Implements IRestServiceImpl.JSONData Dim p As New PointsOfInterest p.layer = "trouwen" p.errorString = "ok" p.errorCode = 0 Dim hs As Hotspot For i As Integer = 0 To 10 hs = New Hotspot hs.id = 1 hs.anchor = "" p.hotspots.Add(hs) Next Return p End Function End Class End Namespace**** IRestServiceImpl.vb
_ _ Function JSONData(ByVal lat As String, ByVal lon As String, ByVal radius As String, ByVal cat As String) As PointsOfInterestI believe what you’re missing is a
p.hotspots = new List(Of Hotspot)before the loop. When you callp.hotspots.Add(hs)the first time,p.hotspotsisn’t an instance of an object yet.That was it! Thanks! :)
Oh, one more thing: the ‘text’ property in the response format has three properties: ‘title’,'description’ and ‘footnote’. How would that be solved in a class definition? I cant do that with a list as well right? Would I have to create a list of another class to solve that issue or…?
An enum works well for those type of properties.
Is there anyway to handle polymorphism when passing back the JSON object?
I have a WebMethod that takes the parent class as an input parameter, and I want to pass in an object of the child class.
Any ideas?
Great work, BTW.
Marie
I believe I just accomplished this by adding the “__type” property to the start of my javascript object. __type should be the name of the child class qualified withthe namespace. So, __type: MyNamespace.MyChildClass. Awesome!
That’s interesting. What did you use for the type of the input parameter on the method when you did that?
The base class.
One more thing, I had to add [GenerateScriptType(typeof(StorageAction))] to my WebMethod, where Storage Action is the name of my derived class.
I am facing problem serializing an object in JSON to match parameter name of WCF function call. The problem is to map the parameter name, i.e. the incoming JSON string should have the starting value as the same name as the parameter being passed in the function e.g.
“{\”GetComplexDataResult\”:{\”BoolValue\”:true,\”StringValue\”:\”Hello World!\”}}”
This is my WCF Function which I call in my client and as you can see the parameter name is same as the one which is being returned “GetComplexDataResult”
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
String SaveData(CompositeType GetComplexDataResult);
The problem which occurs is when I try to serialize my object using either Microsoft
System.Web.Script.Serialization.JavaScriptSerializer or any other library (e.g. Json.NET)
it only returns me {\”BoolValue\”:true,\”StringValue\”:\”Hello World!\”} even if I pass an object of the same class “CompositeType” (This is the client side code) e.g.
CompositeType GetComplexDataResult= new CompositeType();
GetComplexDataResult.BoolValue = true;
GetComplexDataResult.StringValue = “Hello World”;
JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = serializer.Serialize(patchVersion);
My question is how can I get this JSON string
“{\”GetComplexDataResult\”:{\”BoolValue\”:true,\”StringValue\”:\”Hello World!\”}}”
Instead of
{\”BoolValue\”:true,\”StringValue\”:\”Hello World!\”}
with by just passing my object to JSON parser. I can concatenate it manually after I generate my JSON string, but that would be too much time consuming work. Is there any parser which solves this problem
This post would probably be more relevant to what you’re trying to do: http://encosia.com/using-complex-types-to-make-calling-services-less-complex/
Thanks for you your quick reply… I will look further on your suggested link..
Thanks again..
Any idea how can I get dynamic fields? means I don’t have those fields defined as public beforehand in the class. I read somewhere about using GetObjectData like below, but I could not make it work, any idea?
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
throw new System.ArgumentNullException(“info”);
info.AddValue(“AltName”, “XXX”);
info.AddValue(“AltID”, 9999);
}
I don’t have any experience dealing with that specific problem. I can vouch for the fact that returning
dynamicorobjectworks, which you can use to return arbitrary anonymous type objects. That approach might work for you there also.Do you mean dynamic fields that are POSTED as json and you want to map those to a dynamic object w/ dynamic members?
Here’s a post on Stack Overflow which I’ve used previous, and it works great:
http://stackoverflow.com/questions/3142495/deserialize-json-into-c-sharp-dynamic-object
You have no idea how much time I have wasted trying to return properly formatted JSON from an asmx web service to jqGrid via JQuery. OK, maybe you do and that is why you wrote this post and the others in this series. Ay any rate, THANK YOU so much. I can finally start doing some productive work.
I know this article was published ages ago but it’s still relevant.
I just wanted you to know that whenever I’ve had AJAX issues with .NET/jquery it’s always one of your articles I end up finding – and it helps resolve my issues. This one is no exception.
Dave, you truly are a god among men. :)
I have been pulling my hair out trying to get the asmx return jquery and not XML. I finally used the JavaScriptSerializer because I spent an entire day reading google, etc. trying to figure out why the service wasn’t turning my list of entities into JSon string.
I think letting the web service handle this is definitely the way to go, as long as it’s not as cumbersome to code up as it has been for me.
Good blog by the way, I’ve come across your site 3 or 4 times now in the past week!
Sorry I meant “return JSon and not XML,” not jquery… still not awake this morning. :)
Hi Dave
So many great posts – i think i’ve read all blogpost about .net/jquery/json.
I’m a noob developer, and pretty confused, think i’ve used about 4-5 hours trying googling and reading, but i didn’t found a solution.
My issue:
I’ve some data in a mySql db, and i want to provide this data to a phonegap, so i need to use JS in some way, and jquery doing a great job!
But the guide i’ve used( http://williamsportwebdeveloper.com/cgi/wp/?p=494 ) using JavaScriptSerializer and it shoudn’t, cause as you write the response is:
{“d”:”[[\”Tobias Mobil\”,\”152\”,\”Skid skud \”
and not
{“d”:”[[“restaurant_name”:”Tobias Mobil”,”dish_id”:”152,”dish_name”:”Skid skud”
as it should…
My webservice: http://dagensret.com/GetDishes.asmx/GetDishesByDates
So please help me :)
I need an example using data from a mySql database.
Thx in advance
The reason you’re getting the extra, escaped double quotes in the JSON is because that post makes exactly the double-serialization mistake that this post is about. Using JavaScriptSerializer (and the corresponding client-side
eval()) manually is not necessary. To avoid that, you should be able to set the method’s return value tostring[][]and returnJaggedArraydirectly.As for why the data is not key/value pairs, that’s because the method is returning a representation of a DataTable’s rows, not a Dictionary of column names and values. You would need to use a different data access approach to change that. Something that pulls the data out into a
Dictionary, or similar. Rob Conery’s Massive is an example of that approach (not sure if it works with MySQL though).Thx mate!
I’ve used another solution returning a Dictonary.
I’m so happy you’re blogging and i appreciate your help!
/Tobias
If I don’t do double serialization, the response is null.
I’ld really like to clean it up even though it works. Using a ashx Handler,
The “null” response from fiddler validates good, but not the response that works.
client side is like
$.ajax({ ... dataType: 'json', success: (function (result) { for (var x in result) for (var key in result[x]) { $('#' + key).html(result[x][key]); }Thanks for all the good reading here Dave!
When you remove the second level of serialization, you need to adjust your client-side code as well as your server-side code. In your example, if you use this on the server-side:
Then, you need to use JavaScript like this to iterate through the result:
Using two
forloops was trying to descend into the keys of a second level dictionary, but that’s only there if you doubly serialize the data.The response is null but I did figure it out. I had $.ajaxSetup with dataFilter: from http://encosia.com/simplify-calling-asp-net-ajax-services-from-jquery/ but I am not using a “ScriptService” or page method. When I removed the dataFilter, it works.
Hopefully this will help someone seeing a “null” response… How can it be null when fiddler shows valid JSON? Check for a dataFilter!
greate post, solving my confusion in mind for 2 weeks.
I’ve created new ASMX web service and added one parameter to HelloWorld function and added ScriptService attribute to WebService class, so it’s code looks like this:
when I run this webService like this:
it works fine, but when I change it to this:
I get error like this one:
Only Web services with a [ScriptService] attribute on the class definition can be called from script.
But I have added this attribute to web service class. Do you have any idea why it’s still not working properly?
I’m using .NET 2.0
In the first example, it seems to work because jQuery automatically translates that object literal from
{ ID: 2 }to a POST body parameter that traditional SOAP-based ASMX services can understand:ID=2. Unfortunately, that and the lack of an application/json contentType mean that the ASMX service is going to respond with XML, which probably isn’t what you wanted.jQuery is able to detect the XML response via the Content-Type of the response and parses it accordingly. So, it seems to work in this simple case, but you’ll probably run into impedance mismatches between JSON and XML in the long run (not to mention that JSON is faster to parse and lighter over the wire).
Since you’re using .NET 2.0, the most likely culprit is that you’ve got the AJAX Extensions installed, but haven’t updated your web.config to use that new handler for ASMX requests. More info on the exact configuration for 2.0 here: http://encosia.com/asmx-scriptservice-mistakes-installation-and-configuration/
You were right that it had to do with System.Web.Extensions, it was added into web.config, but dll added to the project was in wrong version so it couldn’t work properly.
Thank you so much for help and you have new RSS subscriber :)
Hey Dave! Your posts have seriously helped me out over the past few years.
I was wondering if you could give me a hand.
I have a web service in my .aspx file that both returns an object and takes in an object as a parameter:
this is my jquery statement to pass in the object to the service:
this is the object ‘mObj’:
the issue I have is that when I attempt to send this object to the web service, I get this error:
I’ve been searching for a few days on Google now, but to no avail.
Any ideas as to why I’m getting that error?
I’m using asp.net 4 c#
Have you looked at what exactly
mmInfois being assigned? That error you’re seeing is usually related to an errant'. That’s why you’re seeing the\u0027(and encoded apostrophe) wrapping System.String in the error.What’s that
Stringifyfunction? Is it exactly identical to JSON.stringify?I believe all versions of JavaScriptSerializer allow this issue to pass through, but another problem worth fixing is that your JSON is invalid. Only double quotes are allowed as qualifiers in JSON.
Rolling those two fixes together, what happens if you use this for your data parameter?
data: '{"mmInfo":' + JSON.stringify(mObj) + '}'greate post, solving my qustion, i use angularJS and c# webservice.
thanks all!
Hi Dave!
Just to be sure : if I use ASP.NET 2.0, and if I’m don’t want to install AJAX Extension 1.0, there is no other ways to use your fantastic technic to call and respond with JSON? Meaning that I will have to use a library like Json.NET and serialize/deserialize json by myself (like your “not to do” example)?
And thank you for all your articles about AJAX, JSON and Web Services, they are a real reference for me!
That’s right, you’d need to use something like Json.NET in an HTTP Handler or similar.
I don’t think there’s any reason to avoid installing the AJAX Extensions 1.0 though. That basically just installs the early, out-of-band version of what was eventually rolled into 3.5. It’s in a separate namespace, so you don’t need to worry about introducing problems with existing 2.0 code by installing the extensions.
Could you provide an example of how to pass an object with vb.net?
TIA
I’m trying to take your advice to heart, but I find that, unless I manually serialize on the client, I never get anything returned other than [object Object]. Here’s the code:
webservice.asmx.cs:
webpage.aspx:
In the WebMethod, I can change the return type to List and just return list, but nothing changes. I can also add or remove [ScriptMethod(ResponseFormat = ResponseFormat.Json)] just after the [WebMethod] attribute, and it still just returns [object Object] for either return type. I must be missing something. If you could point out what that is, it would be awesome, because, as it is, I feel like my method implements your example nearly verbatim, but with different results.
As it is, I can serialize that manually on the client using JSON.stringify, but it puts “__type:” before every element, rather than give me the clean JSON I’m trying to get, and which you show in your example. And, as you seem to point out, that’s an unnecessary step.
ASP.NET is returning something like this:
And, [object Object] is the toString value for JavaScript objects. So, that’s what you would expect to see in an alert. The alert function doesn’t automatically expand objects or arrays into a more readable format.
You can verify that the
resultvalue contains a collection of 30 items by alerting its length:Also, you can change that return type back to the List that directly. Lists and arrays are serialized exactly the same way via JavaScriptSerializer, so the ToArray is just an extra step that isn’t necessary.
Ok, tried that, and you’re right about length. Still have some problems. I can’t see the results in the div, unless I use JSON.stringify(). I thought the whole point was to get away from having to do that. Firebug shows I’m getting a JSON response. The other problem, though, is that the response starts with {“d”:[{“__type”:, which is the other thing I’m trying to get rid of. I thought the point of this article was to cure this, because it was symptomatic of unnecessary serialization.
An extra, unnecessary JSON.parse (or, worse, eval) is what you’re avoiding by not doubly serializing the response. JSON.stringify is a convenient way to see a text representation of the object and array, but not really directly related to the serialization situation.
Since you have structured data on the client-side now, you can display it a number of ways. For example, something as simple as (if the rows had a Name property):
Ideally, you’d probably want to use a client-side templating library to render this data. Manually building strings is messy and error prone. I’ve written about using jTemplates in the past, to give you an example of the approach. Today, I’d probably use either JsRender or Handlebars instead of jTemplates, but the approach is exactly the same.
I am intending to save configuration information in SQL. Thought it best to just save it as JSON string in varchar. Create a service that client side can make jQuery AJAX call to receive configuration data. I don’t really need to map the configuration data to an object on the server side. Do you know of any examples how to manage this scenario?
It’s reasonable to send a string of JSON back and forth if the server never needs to understand its structure. The aim of this post is to avoid the situation where there is an object representation on the server side, where it’s needlessly wasteful to serialize that object twice (once to a JSON string, and then that JSON string is also serialized again) on the way to the browser.
Basically, if you find yourself using JavaScriptSerializer (or Json.NET or similar) manually inside a server-side endpoint that automatically handles the JSON serialization (e.g. ScriptServices, Page Methods, Web API, etc), then there’s probably a better approach that works with the framework instead of against it.
Hi Dave – great article and excellent followup. I’m trying to quickly whip up an oEmbed API endpoint. I need to output a raw JSON string, but it won’t be requested with a POST. How can I quickly and easily output a raw JSON string from the object approach you outline above?
Here is an example of what I need to output: http://www.jest.com/oembed.json?url=http%3A%2F%2Fwww.jest.com%2Fembed%2F199639%2Fengineering-students-go-berserk-for-dancers
A request to my endpoint, passing me URL in the querystring, needs to get back a raw JSON string. What’s the easiest way for me to do that?
If you just need to relay that bit of oEmbed JSON from a remote server, using a technique like this one might be a better approach than a full web service: http://encosia.com/use-asp-nets-httphandler-to-bridge-the-cross-domain-gap/
Hi Dave
Thanks for the post. Have a question regarding accepting a nested object from the client side. I tried passing following object and it failed.
[DataContract]
public class CompositeType
{
[DataMember]
public bool BoolValue { get; set; }
[DataMember]
public string StringValue { get; set; }
[DataMember]
public IList Children { get; set; }
}
[DataContract]
public class ComplexTypeChild
{
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
}
[OperationContract]
CompositeType DoSomethingElse(CompositeType composite);
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
public CompositeType DoSomethingElse(CompositeType compositeObject)
{
// method logic goes here
…
}
It seems asp.net service can only translate simple object, or do i need to do something else to work with nested objects?
Thanks
the default translator doesn’t work with nested type. following fails
[WebInvoke(Method=”GET”, ResponseFormat=WebMessageFormat.Json, RequestFormat= WebMessageFormat.Json, UriTemplate=”GetProducts/storedId”]
public ServiceResponse<List>> GetAllProducts(string storeId)
{
}
[DataContract]
public class Product
{
[DataMember]
public string Name {get; set;}
[DataMember]
public IList ProductDetails {get; set;}
}
I had no other option but manual serialize the object to string and pass it back. How do you deal with nested types?
Why people want to do things manually ?
Maybe because JavaScriptSerializer is crappy and limits the total JSON output size…
It defaults to 102,400, but it’s configurable. You can adjust JSS to serialize out megabytes of JSON if you want:
“It just works!”
My arse!
The web.config’s set up (bits below), the web service compiles, I’m returning a string/dataSET, simple object…….
It ALL comes back as XML.
It all just works – except when it doesn’t, and there’s nothing online that gives an idea on how to diagnose the issue.
Are you making the request with a POST and setting the Content-Type to
application/json? You’ll get XML instead of JSON unless your request satisfies those two conditions.Hi, I’m getting a “A circular reference was detected while serializing an object of type ‘System.Web.HttpContext’.” error.
And my Jquery;
Missing something obvious here I presume?!
Thanks.
You’re close. The problem is that you’re mixing your Product object with the WebService object, which has a plethora of complex, interrelated properties that JavaScriptSerializer can’t serialize (specifically because of the circular references between them). What you need to do is separate that out, like this:
Also, you don’t need to
eval()the response in your jQuery code. jQuery will do that automatically when it sees that the response’s Content-Type isapplication/json.Hi Dave,
I have a function that return a complex type which is the query result from the stored procedure and this store procedure had imported as a function in DataService. The reason i do this is because i want to centralize all database related function, entity into single location. By doing this, the dataservice it’s need me to marking all column return from the store procedure as DataMember or CollectionDataContract for collection of data.
So to ease my work, my work around is to manual serialize the result. Because i do not want every time a new Store procedure imported i need to create a class to map the result. So do you have better idea on how should i overcome this if not manually serialize it. If you need clarify on my question please let me know. Thanks a lot first. Hope you can reply on this question.
You can use the
[ScriptIgnore]attribute to control what is serialized by JavaScriptSerializer, similar to what you would do with DataContractJsonSerializer’s attributes (but JSS is a more JavaScript-friendly serializer than DCJS in a few ways).If i’m understand correctly [ScriptIgnore] only apply on single variable.
Just give an example to clarify my question. This “spRC_CampaignHubSpokeByPromoterSelect” Store procedure (SP) will return more than a columns which i do not want to create another class to map the column return from the SP. During compilation that is no error return but when run in the browser it will prompt this error “Type ‘System.Data.Objects.ObjectResult`1[DPPromoterModel.spRC_CampaignHubSpokeByPromoterSelect_Result]‘ cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute”
Below is the function in my dataservice
The specific problem there is that JavaScriptSerializer doesn’t understand how to serialize
ObjectResult. You could work around that by writing a custom JavaScriptConverter class to be invoked for ObjectResult objects. Here’s a rough implementation to do that for dynamic ExpandoObject, for example: https://gist.github.com/Encosia/6cfcdfdf2a117fa5e81bHmm… Thx anyway. But the return result is still same. I still get ‘ugly’ JSON string.
My intention is to reduce the work of create new class for each new store procedure import into entity, it seem like no choice to create new class for each imported SP. Or Leave it ugly :)
What do you mean by “ugly”? If it’s doubly escaped by the time it gets to the client-side, make sure you’re building something like a
Dictionary<string, object>in your custom JavaScriptConverter class, not building a string.Hi,
I debug the code and noticed it did not go into ExpandoObjectConverter. It’s called the standard serialize.
So i changed it to call in this way
and it prompt error
Unable to cast object of type ‘System.Data.Objects.ObjectResult`1[DPPromoterModel.spRC_CampaignHubSpokeByPromoterSelect_Result]‘ to type ‘System.Dynamic.ExpandoObject’.
In your case, you need to create a converter for the ObjectResult class, not ExpandoObject.
If you’re calling JavaScriptSerializer.Serialize() manually in your code, you’re still creating a string and then returning that through the ScriptService, which will serialize it a second time. That’s what this post is about. If you’re manually creating a JSON string inside the method, it will always come back with the “ugly” serialization.
What you need to do for your ObjectResult is create a converter for that type and then register it in the web.config (like this) so that it will automatically be used when you return your ObjectResult.
Hi,
We have been using this technique for years now and it worked pretty well for our needs (ASMX + .NET 2.0 on IIS6.0). Today, IT changed the server to a newer version (MS Server 2008 R2 + IIS7.5) and our web services do not work anymore.
The website and the webservices still works in localhost when launched from Visual Studio 2010 but not on the new production server. The returned error complains about dictionaries serialisation and the result seems to be XML instead of JSON.
Is there something we could do without having to change the source code?
Thanks.
If your application pool changed from “classic” IIS6 mode to the IIS7+ integrated pipeline, you’ll need to update your web.config to move some of the ASP.NET AJAX related configuration to the
system.webServersection instead ofsystem.web.You should be fine other than that though. Otherwise, all of this works the same way under IIS6 and IIS7+.
I wouldn’t call manual serialization using the contract serializer a mistake. When you need to do deserialization on returns the contract serializer is a better solution. The javascriptserializer is much simpler and doesn’t always do what you need.
The problem is that you’re using JavaScriptSerializer with ASMX/ASPX WebMethods regardless. If you do manual serialization work inside your method, that result is still running through JSS on the way out and then you have double the work to do on the client-side too.
If you want to use a custom serialization approach, it’s better to use something closer to the metal like an HttpHandler.
For typical client-side work, JSS is better than DCJS (which is why DCJS was dropped in favor of Json.NET in Web API). JSS handles anonymous types, enums, and dictionaries better. If you need to tweak how it handles certain types, you can always register a JavaScriptConverter to override how it handles a particular type. It’s better to do that and work with the framework than manually serialize data and end up with double serialization work on both server and client.