Welcome to Part 3 of a multi-part series on JavaScript Object Notation (JSON) support in the Microsoft .NET Framework. In this article, we'll focus on performing JSON serialization from a RESTful WCF web service. You can find the other parts of this series at these locations:

  • Part 1 - An exploration of the DataContractJsonSerializer class
  • Part 2 - An exploration of the JavaScriptSerializer class
  • Part 3 - JSON serialization from WCF (including a REST primer)
  • Part 4 - Using the JavaScriptConverter class to customize JSON serialization

Welcome back. In Part 1 of this series, we looked at using the DataContractJsonSerializer to dehydrate and rehydrate .NET classes to and from JavaScript Object Notation (JSON), respectively. In Part 2, we looked at the once rogue JavaScriptSerializer class which has the unique capability of being able to serialize Plain Old CLR Objects (POCO) that aren't marked as [Serializable] or [DataContract]. In this article, we'll focus on something a bit less academic: building a RESTful web service with Windows Communication Foundation (WCF) that delivers JSON encoded objects to its clients.

A Representational State Transfer (REST) Primer

Let's do a little rundown of what Representational State Transfer (REST) means. Like any architectural pattern, REST has some tenets or guidelines for describing what it hopes to accomplish and, in some sense, how it prefers for the work to be done. The REST principles1 for application development are:

  1. Application state and functionality are abstracted into resources
  2. Every resource is uniquely addressable using a universal syntax for use in hypermedia links
  3. All resources share a uniform interface for the transfer of state between client and resource, consisting of:
    • A constrained set of well-defined operations
    • A constrained set of content types, optionally supporting code on demand
  4. A protocol which is client-server, stateless, cacheable and layered

We don't need to cover all of these but there are a couple of high points to take note of. Most people interpret the phrase universal syntax in the second principle to mean that URLs are to be used to address application resources. And that's usually true. Here's the resource identifier for my Twitter.com timeline, for example:

http://twitter.com/statuses/user_timeline/KevinHazzard.xml

If you click that link, you'll get an XML document that contains the state of my status updates to Twitter.com. The term for this kind of output is Plain Old XML or POX for short. If you change the extension of the resource identifier from xml to json in the URL shown above, what do you think you'll get? That's right. You'll see my Twitter.com timeline in JSON format. Pretty cool, huh? You can learn more about the RESTful Twitter Application Programming Interface (API) if you're interested.

The key word in that second principle is uniquely. What it means is that the resource identifier for the application state of my user timeline on Twitter.com must be different from all the other resource identifiers. Perhaps it's stating the obvious but from an addressing standpoint, REST tends to refer to application state and functionality like a file system. Bits of application state and the functions that an application performs are like a set of files. If you open a file by a well-known name, you'll get the functionality or state that's inside the file. This, of course, helps to define what the first and third REST principles mean, too. In the RESTful URL above, the well-defined operation is not KevinHazzard.xml. That's an argument or parameter, if you will. The operation is user_timeline and, reading left to right, you might guess that it's inside a module called statuses. It doesn't mean that the Ruby code that Twitter.com uses to implement the service is organized that way. But the resources in that class have a constraint that they use to provide a set of uniquely addressable resources.

The sub-bullets of the third REST principle are really interesting to me. One of the complaints about the Simple Object Access Protocol (SOAP) that some web services use is that it's much too rigid to be useful for web application development. Web developers complain that they don't have a Software Development Life Cycle (SDLC) that allows them to digest Web Service Description Language (WSDL) contracts, generate proxy classes and re-compile their code to use the well-defined operations and content types that a web service might provide. But I see through the compaints and the dissatisfaction with SOAP and the SDLC it engenders. The heart of the complaints really have more to do with the fact that great tools for building SOAP clients are rare. Case in point: over the years, I've demonstrated various ways to call SOAP services from environments that don't have great web service support built in. In an article I wrote about invoking SOAP web service from a dynamic language like Windows PowerShell, I demonstrated that WSDL contracts can be consumed at runtime to create and call proxies to SOAP services on the fly. To do that, I had to write a class called WSDLHelper that performs dynamic code generation. Not simple stuff but it works beautifully, making access to SOAP-based services just as easy as calling RESTful services from PowerShell or Python, for example. So, it's not that SOAP is bad, per se. But the tools to make SOAP client development aren't all that great, even in some .NET contexts.

Those sub-bullets of the third REST principle speak to the desire to constrain and define the operations and the data types that flow to and from the service. Without some contraints, the experience of using a RESTful service would be chaotic and unpredictable. Services like Twitter.com have very detailed definitions for their RESTful resources outlined in the Twitter API. It defines the resources (operation contracts), the parameters, the authentication mechanism and the output schema (data contracts) for each resource. Well, that's no different than what SOAP and WSDL are attempting to describe. The fundamental difference, though, is that SOAP and WSDL have rigid and quite rich XML schema definitions for all of that, not just the output of each resource. So, when people say that they dislike SOAP because it's too complex or bulky, look through the veil and understand that they really only dislike parsing WSDL, generating proxies, recompiling code, etc. It's OK to dislike those things, but now that you've read my blog, you understand that if better SOAP client tools existed on more platforms, it would often be preferred due to the richness and type safety that it can lend to the design process.

RESTful WCF

OK, enough about REST principles. Let's look at what it takes to expose a RESTful service in WCF. There are a handful of simple steps you can follow to do this. Assuming that you're going to be using Internet Information Server (IIS) to expose your service, follow these steps:

  1. Add a reference to System.ServiceModel.Web to your web application. This assembly includes the implementations of the WebServiceHostFactory and the WebGetAttribute that you'll be using in the next steps.
  2. In your Web.config file, modify an existing endpoint or add a new endpoint that uses the webHttpBinding binding type. This binding tells WCF that we're going to use HTTP URLs to parse resource identifiers and parameters. It also makes it possible to use RESTful response formats like POX or JSON instead of generating SOAP envelopes to go back to the client.
  3. In the SVC file for the WCF service, modify the <@ servicehost=""> element to include the attribute Factory="System.ServiceModel.Activation.WebServiceHostFactory". This factory class provides instances of the WebServiceHost class to handle the parsing of incoming RESTful URLs.@>
  4. The last thing you need to do is mark each [OperationContract] that you want to act as a REST resource with the [WebGetAttribute] or the [WebInvokeAttribute]. This is where we'll provide a template that maps incoming URLs to specific operations. These attributes also allow us to map parameters from the URLs to each operation's parameters.

Here's some example code and configuration for my ThingySearchService. Let's start with the [DataContract] and the [ServiceContract]:

using System.ServiceModel;
using System.ServiceModel.Web;
using System.Runtime.Serialization;
 
[DataContract]
public class Thingy
{
 [DataMember]
 public string Name { get; set; }
 [DataMember]
 public int ID { get; set; }
 [DataMember]
 public int Age { get; set; }
}
 
[ServiceContract(Namespace = "gotnet.biz:JsonPlay")]
public interface IThingySearchService
{
 [OperationContract]
 [WebGet(UriTemplate = "FindThingy?age={age}&name={name}")]
 Thingy FindThingy(int age, string name);
}

First of all, notice that the [DataContract] attribute is explicitly applied to the Thingy class and that each property is marked with a [DataMember] attribute. The serializers used by WCF to render POX and JSON require this. You could alternatively mark the Thingy class with the [Serializable] attribute but as we saw in Part 1 of this series, the DataContractJsonSerializer often does a better job when the [DataContract] attribute is used instead. The UriTemplate of the [WebGet] attribute tells the WebHostFactory that when URLs referencing the FindThingy resource identifier are encountered, they should be routed here to the FindThingy operation. In addition, the UriTemplate instructs the WebHostFactory how to map the parameters in the URL to the underlying method's parameters. For my ThingySearchService, the following URL:

http://localhost:51976/ThingySearch.svc/FindThingy?name=Kevin&age=44

might render this XML:

[ServiceContract(Namespace = "gotnet.biz:JsonPlay")]
public interface IThingySearchService
{
 [OperationContract]
 [WebGet(UriTemplate = "FindThingy?age={age}&name={name}", ResponseFormat = WebMessageFormat.Json)]
 Thingy FindThingy(int age, string name);
}

Now, when I invoke my ThingySearchService, I get a JSON-encoded string containing the text '{"Age":44,"ID":1682,"Name":"Kevin"}' which can be cleanly and quickly deserialized into an object on a variety of browsers and platforms. That was a roundabout way of showing you how to build REST/JSON web services with WCF. Hopefully you found the background information helpful. In the next segment, I'll be looking into how you can exercise finer control over the JSON serialization process.

Footnotes:
1 - From http://en.wikipedia.org/wiki/REST