JSON in Classical Web Services ASMX

Most of the websites we see these days have great user experience by providing asynchronous postbacks and means of data transport has been JSON. Even though most of us have already migrated to new versions of .NET, there are still some people using the older versions. This post is about supporting JSON in Classical Web Services (.asmx).

Add a new ASMX web service file as usual. Then decorate your class with [System.Web.Script.Services.ScriptService] attribute as shown below.

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class JsonWebService : System.Web.Services.WebService
{
    // code omitted for brevity
}

Then decorate your methods with [System.Web.Script.Services.ScriptMethod(ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)] attribute.

[WebMethod]
    [System.Web.Script.Services.ScriptMethod(ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)]
    public string HelloWorldInJson()
    {
        // code omitted for brevity
    }

We will then return a JSON string. To make it easy we will be using a 3rd party open source JSON serializer/deserializer which can be found at http://json.codeplex.com

Let’s make a helper method to make it easier to convert an object to JSON string.

public class JsonHelper
{
    /// <summary>
    /// Convert Object to Json String
    /// </summary>
    /// <param name="obj">The object to convert</param>
    /// <returns>Json representation of the Object in string</returns>
    public static string ToJson(object obj)
    {
        return Newtonsoft.Json.JsonConvert.SerializeObject(obj);
    }
}

Then you call the JsonHelper.ToJson() method to serialize the object to json as follows.

 

[WebMethod]
[System.Web.Script.Services.ScriptMethod(ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)]
public string HelloWorldInJson()
{
    return JsonHelper.ToJson("Hello World in Json");
}

You can also convert your own objects (classes) to string by calling the Helper method easily.

The other alternative i.e. without using the Newtonsoft.Json could also be done. Instead of returning string one could return the Object itself. For instance let’s assume we have the class Person as below.

public class Person
{
    public string Name;
    public Gender Gender;

    public List<string> Hobbies;
}

public enum Gender
{
    Male,
    Female
}

[WebMethod]
[System.Web.Script.Services.ScriptMethod(ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)]
public string ReturnComplexObject()
{
    return JsonHelper.ToJson(JsonHelper.CreateSamplePerson());
}

And let us also assume that we have a method called JsonHelper.CreateSamplePerson() which return a new instance of the Person class. We could then write it as below. Notice the return type is Person instead of string.

 

[WebMethod]
[System.Web.Script.Services.ScriptMethod(ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)]
public Person ReturnComplexObjectRaw()
{
    return JsonHelper.CreateSamplePerson();
}

 

We would get the following result for the ReturnComplexObject() where the return type is string. Notice that it is not fully JSON as it contains mixture of XML. this is because the content-type is not set to application/json.

image

When the content-type is set to application/json the following result is obtained.

image

It now gives a JSON string.

Now for the ReturnComplexObjectRaw() which returns the Person the following result would be obtained. (The object is converted automatically to JSON.)

image

What is the difference of returning converted JSON string using the Newtonsoft Json and or the autoserializer returning the Person Object?

  1. First of all as you can see the autoserializer from done by .NET adds one more field called __type. This isn’t much of a problem though. __type is added only if the Object is complex. For simple types such as string, it is not added.
  2. Secondly the result returned by .NET autoserializer returns JSON object while from Newtonsoft it return a JSON string which needs to be converted to JSON object manually (more of this in the coming posts). That is why you can see a lot of \” in the result by Newtonsoft. Its actually an escape sequence character for the string.

OK. But which method to choose then?

Well, that is quite a tough question. But from my experience I have choosen to use Newtonsoft  by serialize the object and returning it as a string rather than using the concrete object. This was due to the fact that, some of my classes doesn’t contain a constructor without any parameters (default constructor) such as below.

 

public class Student
{
    private string _firstName;
    private string _lastName;

    public string FirstName
    {
        get { return _firstName; }
        set { _firstName = value; }
    }

    public string LastName
    {
        get { return _lastName; }
    }

    public Student(string firstName, string lastName)
    {
        _firstName = firstName;
        _lastName = lastName;
    }
}

 

It doesn’t have a constructor. Then if I return Student in my Web Service it would throw me the yellow screen of death. Where as using the Newtonsoft serialization it would work great. The another reason is that in WCF to serialize an object to JSON using DataContract it needs both get and set properties, but the LastName in Student class doesn’t have set property. This would not include LastName in the serialize JSON string which was not what I wanted. So the safer way for me was to use Newtonsoft.JSON.

These preferences are from my own perspectives. If you find that it is not good to use Newtonsoft over .NET default serialization or have a better one, please feel free to leave a comment.

In the later posts I will explaining how to consume these JSON webservices using Jquery. If you want to learn how to consume these services using JQuery, you can read it at http://blog.prabir.me/post/Consuming-ASPNET-Web-Services-using-JQuery.aspx.

AsmxJson.zip (761.21 kb)


blog comments powered by Disqus