Returning JSON from WCF Web API

IMPORTANT The WCF Web API has recently been merged with ASP.NET MVC 4 beta with a new name ASP.NET Web API. Although there are some changes in the api the core idea discussed in the article still applies there - 2/16/12

What is WCF Web API?

WCF Web API is Microsoft's answer for creating RESTful services. Currently it is in preview state and you can download the binaries from here. For the people who are not aware of RESTful services, a RESTful service is a simple web service implemented using HTTP and that can be communicated using the normal GET, POST and other HTTP methods. Exposing a class as a RESTful service makes it easily accessible by wide variety of browsers and devices. In WCF Web API the REST service class is typically called as a resource and the format in which they exchange data is called as media type (ex. XML, JSON etc). In this small article I’m going to tell you how we can make the service to return data in JSON media-type.

Let’s assume we have a method called GetRecentPosts() in a class named PostResource that returns all the recently published posts in a blog.

public class PostResource
{
    public IQueryable<Post> GetRecentPosts()
	{
		// return the recently published posts
	}
}

To expose this class as a RESTful service just mark it with [ServiceContract] attribute. The method can be exposed by decorating with either [WebGet] or [WebInvoke] attributes.

[ServiceContract]
public class PostResource
{
    [WebGet]
    public IQueryable<Post> GetRecentPosts()
	{
		// return the recently published posts
	}
}

One more important thing we have to do is map a route for this PostResource class and that can be done in the Application_Start event of Global.asax.cs.

RouteTable.Routes.MapServiceRoute<PostResource>("Post")

If you don’t do the above step then you will get endpoint not found exception. Suppose the service is running in localhost:5555 then you can acces the service method by the url http://localhost:5555/Post/GetRecentPosts. When you hit the url in the browser address-bar you will see all the recent posts returned in XML format. Since parsing JSON is easy than XML in JavaScript let see how we can make the service return media-type as JSON.

When you look into the other properties of WebGet attribute you’ll see two enumeration properties like RequestFormat and ResponseFormat. Let set the ResponseFormat as WebMessageFormat.Json.

[WebGet(ResponseFormat = WebMessageFormat.Json)]
public IQueryable<Post> GetRecentPosts()
{
	// return the recently published posts
}

If you refresh browser expecting to see the JSON data you’ll surprise seeing again the same XML that you are not interested upon. So what happened? Do we want to set some other properties or configure some other things in the service side? The answer is the WCF Web API returns data in particular media-type based upon the client’s request i.e. based upon the value (media-type) they pass in the Accept property of the request header. Since you are not setting the Accept header as "application/json" you always see the data always returned in the default XML media-type. Then what this property ResponseFormat is doing there? after asking this question in forums I got the answer that the API team maintains this property for backward compatibility atleast at this time of writing this post. Let see how we can set the Accept header.

jQuery

If you are consuming the REST service using jQuery then you can easily do that by passing dataType as "json".

$.get("/Post/GetRecentPosts", function() { /* callback method */ }, "json");

Passing "json" as the dataType parameter sets the Accept property in request header as "application/json".

Other JS libraries

If you are using some other JS library like ExtJs (in my case) then,

Ext.Ajax.request({ url        : "/Post/GetRecentPosts",
                   method     : "GET",
				   headers    : {
						"accept" : "application/json"

				   },
				   callback    : function(){ /* callback method */ }
                });

XmlHttpRequest

If you are directly using XmlHttpRequest object then,

var xmlhttp = new XMLHttpRequest();
...
xmlhttp.setRequestHeader "Accept", "application/json";

Summary

So the summary is when you are using WCF Web API for creating RESTful services please make sure you are passing the right media-type in the Accept header to get the data in the expected format.

Other References

To learn more about WCF Web API check these links.

blog comments powered by Disqus