Introduction
I have tried to find out how I can return JSON formatted data from a Web Service and how I can parse data with JQuery. I needed to know how I can return JSON data from a Web Service and how I can parse the data from client-side using JQuery. I have not found so much detailed information or a full article from where a developer can start. So, I decided to write this article. When we develop an application that will communicate with a remote computer, a data format for this communication need to be selected and implemented. For a Web Service, XML based SOAP is rife and widely accepted. While XML works fine with many scenarios, it has some drawbacks that makes it difficult to use in some scenarios. One such scenario is AJAX-style Web Services, where XML is difficult to process on the client side. Also, XML is larger in size than its corresponding JSON representation. For each property, XML has two tags: opening and closing. On the other hand, JSON has the property name only once.
What is JSON format?
JSON is a lightweight data-interchange format. Like XML, it is human-readable, platform independent, and enjoys a wide availability of implementations. JSON is a subset of the object literal notation of JavaScript. Data represented in JSON can be parsed by JavaScript easily, so it is ideal for AJAX based web applications. For your information, JSON does not have any support for datetime as JavaScript doesn't have its own datetime data type. Rather, datetime in JavaScript is an object. You can read here details on how JSON datetime is handled in AJAX.
Why should you care about JSON?
Let’s say you need to develop an auto-complete textbox as Google Suggest as shown in figure 1. While the user is typing, you need to fetch data from the server with a Web Service and need to show below the textbox. Now let’s say your web service is returning XML data. One of the main challenges in this auto complete feature is how interactive your auto complete feature is. If you can save just one second in showing the suggestion list, you will benefit 10 times.
Figure 1: Google Autosuggest
If a Web Service returns XML data, then the data to be passed from the server to the client is larger than what it would be in the case of JSON. So, using JSON, we only need to pass fewer amounts of data. Also, XML parsing on client side is cumbersome and costly in the perspective of processing. If there’s another easier way, then why should not we use that? Let’s assume the following XML data is returned by the Web Service.
<Product>
<ProductID>1</ProductID>
<ProductCode>p_1</ProductCode>
<ProductName>a Product 1</ProductName>
</Product>
To parse data on the client-side, you’ll need to use JavaScript XML features.
On the other hand, if the Web Service returns JSON format, then the same data is represented as:
{"ProductID":1,"ProductName":"a Product 1"}
So here, we can see that the JSON representation is much smaller in size than its equivalent XML representation. Also, we’ll see later how easy it is to parse JSON formatted data.
Requirements
The code and concept described in this article is .NET framework 3.5. The JSON serializer described later is only supported in .NET framework 3.5. To use the attached code along with this article, you need Visual Studio 2008 Service Pack 1.
Changes in Web Service to make it JSON enabled
You need three types of changes in a Web Service to enable JSON. First, register a JSON serializer in web.config. Then, you need to apply a few attributes to the class whose instances you want to represent in JSON. Then, in the Web Service method, you need to serialize the object before returning to the client.
1. Make sure the JSON serializer is defined in web.config
If you configure your site for .NET Framework 3.5, you’ll get the JSON serializer section automatically added to your web config file. Just to make sure that your web config is not missing an entry for ScriptJsonSerializationSection
, check the entry shown below exists in your web.config as shown in figure 2.
<section name="jsonSerialization"
type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions,
Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
requirePermission="false" allowDefinition="Everywhere"/>
Figure 2: JSON serializer section in web.config
By default, the ScriptJsonSerializer
limits the JSON string to a length of 102400 (UTF-8) characters. If you need to change the maximum length of the JSON string, then change the maxJsonLenght
property of JsonSerialization
. In the section shown below, the max length is changed to 5000 characters:
<configuration>
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="5000"/>
</webServices>
</scripting>
</system.web.extensions>
</configuration>
2. Make the object serializable
For serializing our objects in JSON, we’ll use a data contract serializer, System.Runtime.Serialization.Json.DataContractJsonSerializer
. There’s another serializer called System.Web.Script.Serialization.JavaScriptSerializer
which also can be used for JSON serialization, but this class was deprecated in .NET Framework 3.5 and undeprecated again in .NET Framework 3.5 SP1. Both JavascriptSerializer
and DataContractJsonserializer
have their own benefits. JavascriptSerializer
supports anonymous types and plain string. DataContractJsonSerializer
, on the other hand, works with complex objects mainly designed for WCF, and can format date time in UTC format. In this article, I’ll show how to use DataContractJsonserializer
. You need to apply some attributes to your class to make its objects to be serializable by the JSON serializer. Your class needs to apply the attribute [System.Runtime.Serialization.DataContractAttribute]
if you want its instance to be serializable by the JSON serializer. Also, you don’t want all public properties of that class to be serialized. Only those properties you want to serialize need to be set the attribute [System.Runtime.Serialization.DataMemberAttribute]
. The data contract model, used by JSON serializer, is an “opt-in” model. Applying the DataMemberAttribute
to a field or property explicitly specifies that the member value will be serialized. In contrast, the BinaryFormatter
(mainly used in remoting) serializes public and private fields of a type, and the XMLSearilzer
(used in Web Services for SOAP formatting) serializes only public fields and properties of a type. So, using the binary formatter or XML formatter, you don’t have much control with which filed or properties are serialized. But, with this contract models used by DataContractSerializer
, you can specify explicitly which filed or properties you want to serialize.
As shown in figure 3, I have a product class with three properties: Product ID, Product Code, and Product Name, and I want instance of this product class to be serialized by the JSON Serializer. So, I have applied the DataContractAttribute
attribute to the product class. Also, I want only the Product ID and Product Name to be serialized but not the Product Code. So, I have applied the DataMemberAttribute
attribute to only the Product ID and Product Name.
Figure 3: Changes in Class to Serialize to JSON
3. Prepare the web service method to return JSON formatted data
The first thing to make sure for the Web Service is that the attribute [System.Web.Script.Services.ScriptService]
is applied to the Web Service class. This attribute will make sure that the Web Service is callable from script. The Web Service method which will return the JSON data needs to apply the attribute [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
which will tell the client that the Web Service will return JSON formatted data. Also, the Web Service’s method return type will always be string.
Figure 4: Web method returning JSON data
To format data in JSON, you need to use System.Runtime.Serialization.Json.DataContractJsonSerializer
. You need to pass the type of object you need to serialize to this DataContractJsonSerializer
. Then, create a memory stream and serialize the object to the memory stream. Finally, you need to convert the bytes in the memory stream in string and return to the client. In the following code snippet, yourObject
is the object you want to serialize. In real life, this may be a product, customer etc.
DataContractJsonSerializer serializer = new
DataContractJsonSerializer(yourObject.GetType());
MemoryStream ms = new MemoryStream();
serializer.WriteObject(ms, yourObject);
string jsonString = Encoding.Default.GetString(ms.ToArray());
ms.Close();
Call the Web Service with JQuery
To call the Web Service from client-side, I have used JQuery’s ajax
method. In JQuery’s ajax
method, you need to set the request type to post, as an AJAX Web Service (by default) doesn’t allow methods to be called via the HTTP GET method (how to enable HTTP GET in a Web Service?). For your information, ASP.NET AJAX controls like UpdatePanel
uses HTTP POST when sending asynchronous requests. Below is the JQuery method that will call the Web Service method.
$.ajax({
type: "POST",
data: "{'prefix':''}",
url: "/YourWebService.asmx/MethodName",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: functionToCallWhenSucceed,
failure: funcitonToCallWhenFailed
});
In the above code, ‘type’ is the HTTP POST request as ASP.NET AJAX’s JSON serialized services require a POST request. ‘data’ is the names/values pair for the parameter of the Web Service method. If the Web Service method doesn’t take any parameter, then you need to pass empty curly braces. The reason for this is that IIS requires content length to be provided for all POST requests. If ‘data’ is not provided in the AJAX request, then content-length for the request is not available as jQuery doesn’t set that header automatically unless there is a data parameter. So, in case of calling a no argument Web Service method, the ‘data’ parameter should be empty curly braces. Here are two examples of data parameters. The first one is used for calling a Web Service method which does not take any parameter. The second one is used to call a Web Service method which takes two parameters: SiteName
and PostedDate
.
data: "{}"
data: "{‘SiteName’:’CodeProject’,’PostedDate’:’1 jan 2009’}"
‘url’ is your Web Service name and then the method name. ‘contentType’ and ‘dataType’ is set for JSON format in the code snippet. The ‘success’ and ‘failure’ attributes in the JQuery ajax
method call are two function names that will be called when the ajax
call succeeds or fails correspondingly. The methods (will be called in case of success or failure) will have only one argument that will, in case of success, will be the response, and in the case of failure, will be the error message. The method will be like:
function ajaxCallSucceed(response) {
}
function ajaxCallFailed(error) {
}
One the Web Service call succeeds, your ajaxCallSucceed
method will be called. Then, you can parse the response as shown below. To convert a JSON text into an object, you can use the eval()
function. eval()
invokes the JavaScript compiler. Since JSON is a proper subset of JavaScript, the compiler will correctly parse the text and produce an object structure. The code below assumes that the response is a collection of products in JSON format:
function ajaxCallSucceed(response) {
var products = eval('(' + response.d + ')');
for (var i = 0; i < products.length; i++) {
}
}
The result can be found in the property ‘d
’ of the response object. The extra parentheses are used to make eval
unconditionally treat the source input like an expression. The eval()
function evaluates a string and executes it as if it was script code. So, it can compile any JavaScript program; that’s why eval()
should be used when source is trusted. An alternative is JSON parser which only recognizes JSON text.
How to use the code?
The code attached along with this post has a Web Service named JsonWebService.asmx. The Web Service has only one web method named GetProductsJson
. This method takes an argument named prefix
. If prefix
is not empty, then the method returns ten products (in JSON format) whose names start with the prefix. If prefix
is empty, then it just returns ten products in JSON format. Here, the ProductFacade.cs file in App_Code is like the business layer which returns products. But, no database is used here; rather, it creates ten products by using a for
loop.
Conclusion
JSON is lightweight and easy to use. So, we can easily use this format in AJAX/asynchronous web applications. For example, we can use this format in ICallback
, Page Methods, and definitely in Web Services. We can use this format even in an XMLHttp Request.