WCF REST service with XML / JSON response format according to Content-Type header

Recently I tried to grasp the basics for the WCF REST service and the differences compared to the normal web services versus REST.
I have only tried to basics of WCF REST and not gotten deeper then the shallow level, but this is what I found so far.

If you do not know what REST stands for and why it could be of any use, you can watch this 1h18m08s video on channel9 by Aaron Skonnard:
http://channel9.msdn.com/Blogs/matthijs/Why-REST-by-Aaron-Skonnard 

My solution setup looks like this:

WCF Rest service with XML and JSON

I have a WCF Service Application called “WCF.Rest.Service”, which has a WCF Service called “RestService”.
Our REST WCF service contract looks as following:

WCF REST Service with WebGet and WebInvoke

Notice we added a reference to System.ServiceModel.Web and we are also using this namespace as it is holding the necessary stuff for the REST WCF services.
Instead of using OperationContract we are using WebGet and WebInvoke for REST WCF services.

WebGet stands for retrieval operations and is a HTTP GET operation.
WebInvoke stands for POST requests and stand for the HTTP PUT, HTTP DELETE and HTTP POST operation

1. WCF Rest Service WebGet operations

We have an operation defined GetEmployees, which is marked with the REST WebGet attribute:

WCF REST service with WebGet and UriTemplate

This is an operation that returns a list of all employees. We also set a System.ComponentModel.Description attribute at the operation which described the operation. I will show you why soon.
Since this operation is only a retrieval of information we use the WebGet attribute, which results in an HTTP GET request.
At the WebGet attribute we define an UriTemplate, which is set to “/Employees”. This means if we would visit the http://localhost/WCF.REST.Service/RestService.svc/Employees we would be invoking this GET operation and we should get a list of all employees present in the repository.

Let’s quickly run over some of our code and configuration, so we do not have to cover this again.

The configuration of the WCF REST Service:

WCF REST service configuration

We use a webHttpBinding, which is used for REST services. Notice we also defined an endpointbehavior, where we define the WebHttp and some of the settings.

helpEnabled: Allows you to enable help information of your REST Service. Allows people to see what HTTP operations are possible, on what url’s and what the description of the operation is, if you specified it.
defaultOutgoingResponseFormat: Let’s you chose the default outgoing response format. In our case we chose XML over JSON.
automaticFormatSelectionEnabled: Let’s you enable to control the outgoing format of the responses according to the content-type request header. If you define the content-type header as application/xml the resul will be provided in XML. If you define content-type header application/json, the result will be provided in JSON

Notice we also set aspNetCompatibilityEnabled to true on the serviceHostingEnvironment.

Our WCF service is hosted in our local IIS:

WCF REST service in IIS

Our WCF service can be found at our local url: http://localhost/WCF.Rest.Service/RestService.svc
I made a static EmployeeRepository, which is less effort then creating a database, and acts as our information store we work against:

WCF REST Services

The service implementation for GetEmployees operation (I cut some code out of the service implementation):

WCF REST Service AspNetCompatibilityRequirements WebGet

One of the things to notice is that we set the AspNetCompabilityRequirementsMode to required, making requests to the WCF service run through the ASP.NET HTTP pipeline.
We also work with a Single instanceContextMode, because of the static repository we work with and we do not want to lose data after subsequent requests.

So all it does is return a list of employees, which are present in the static EmployeeRepository.
So basically we have 2 employees in our static repository, so if we visit the /Employees url, we should get those 2 employees listed.

Let’s start by visiting the following url:
http://localhost/WCF.Rest.Service/RestService.svc/help

The result we get:

WCF REST service HelpEnabled page

This is the result of our HelpEnabled setting at the WebHttp node of our endpoint behavior. If HelpEnabled is not set to true, this information will not be visible. As you can see, the operations we defined (the 5 operations our service contract has) also have a description, for people using our REST service. The description is the description we defined at the System.ComponentModel.Description attribute at our service operations.
You can also drill down into the operations and see what response formats you can expect from certain operations.

If we now visit our service at the location http://localhost/WCF.Rest.Service/RestService.svc/Employees we get the following result:

WCF REST service XML response

Click to see the full image. But if we visit the url in our browser, we get an XML response back, containing 2  employees, those defined in our static EmployeeRepository.

From now on we will use Fiddler2 (http://www.fiddler2.com/fiddler2/) to make HTTP requests on our service, as it allows us to play nicely with headers and HTTP POST requests.
Let’s make the same GET request again for all employees with Fiddler:

WCF REST service Fiddler application/xml content-type

Notice we execute an HTTP GET request at our /Employees url (which matches the UriTemplate of our WebGet GetEmployees operation, so that is the operation we invoke) . We also set the Content-Type to “application/xml; charset=utf-8″. So we make a GET request for the employees and we specify that we want XML as a result:

WCF REST service XML content-type

As you can see, we got an XML result back from our GET request.
Let’s do the same request, but get JSON results back:

WCF REST service content-type application/json

And the result of our JSON content-type request:

WCF REST Service with JSON content-type response

As expected, we get a JSON parsed response, which is a quite nice feature. We get a response back in the format we want, depending of our Content-Type header. Do we need JSON and XML responses for certain scenario’s, it’s possible all with exact the same code. Note this is only possible because you set the automaticFormatSelectionEnabled to true at the WebHttp at our configuration behavior. If you do not set this to true, the response format will not rely on the Content-Type request header, but will return in the format that is defined as defaultOutgoingResponseFormat, which is XML by default.

Let’s look at our operation to retrieve the information of a specific employee. We want to get the information of 1 specific employee, so we need a way to pass the ID of the employee, to know what employee we want to request the information about.

Our service contract operation:

WCF REST service webget operation

Our GetEmployee operation takes an ID string as parameter, to know which employee we want information about. That means our REST url a consumer can request employee information, should contain this employee ID. Our UriTemplate is set to “/Employees/{id}”, meaning the url ending at /Employees/5 will result in the 5 being passed as the id parameter for our GetEmployee operation. If you would invoke a url ending at /Employees/xxx the id parameter would xxx. If you visit the url ending at /Employees, you get the list of all the employees again.

Our service implementation for this operation:

WCF REST Service

So if we visit the service url ending with /Employees/1 we request the employee information of the employee with ID 1, which is my information in this case:

WCF REST Service GET

If we would retrieve information from /Employees/5, which is employee with ID 5, which is not existing in our store, you will get a 404 status code back, meaning the resource is not found.

2. WCF REST Service WebInvoke operations

We have an operation AddEmployee, which will add an employee to our repository. This is a POST operation, as it posts data from the client to the service, meaning we have a WebInvoke operation:

WCF REST service WebInvoke

Our Method is POST, matching a create CRUD operation. We have an UriTemplate of /Employees. This means people can do a POST HTTP request to /Employees with the new employee information, and the employee will be added to our EmployeeRepository.

It is important to understand that the HTTP request at /Employees will not return the list of employees now. When we issue an HTTP GET request, it will return a list of the employees. However now we will issue an HTTP POST request, which will be linked to our AddEmployee, which is the POST request listener on /Employees.

Our service implementation of AddEmployee:

WCF REST service WebInvoke

Let’s invoke this AddEmployee operation with Fiddler. First of all we need to know what sort of data we need to send with the HTTP POST, since we need to send information that matches the Employee data contract.
If the help is enabled, we can easily get the expected employee format from there:

WCF REST service help enabled

Click the POST method:

WCF REST service request format

It shows what the employee post information should look like in XML. So let’s copy this thing into our Fiddler and make it a POST HTTP request at the /Employees:

WCF REST service make POST request

If we execute this, let’s get the /Employees again by an HTTP GET request and see what the results are:

WCF REST service POST request

Our employee has been added, by the HTTP POST request we made and with the information we send with the POST request.

The HTTP PUT request to update an employee, would be identical to the HTTP POST request:

WCF REST service PUT operation

The UriTemplate is identical, but the HTTP method will be PUT instead of POST. We also need to pass on an employee in the HTTP PUT request, ideally an employee that exists, or you will most likely get an error. Our service knows which operation is invoked at the /Employees url, due to the difference of the GET, POST or PUT HTTP method.

Our HTTP DELETE WebInvoke operation is identical to our HTTP GET of a specific employee, except that it is a WebInvoke instead of a WebGet

WCF REST service with JSON and XML

We also need to specify the ID of the specific employee we need to delete, so we pass it on as /Employees/2, for which 2 is the id parameter of the operation, specifying we want to delete the employee with ID 2

3. What about invoking these operations from a client and getting the necessary information

I haven’t really tested much with a client, but this is how you can invoke an operation from the client:

WCF REST client

Note we use the a httpWebRequest which is being invoked on our REST locations. We define the Method of our request, in this case a GET.
We get the response from our request and using a DataContractSerializer we convert the response result to a list of employees.

There’s only 1 thing you still need to account for and it is the Employee object, which you by default do not have at the client.
In my case there were 2 possibilities: Add a service reference to the REST service as we published the metadata, so the used data contracts would be imported and you could use them from there.
Second possibility was to get the Employee class according to the information published at the Help page:

WCF REST Service import data contracts

As you can see, there is an XSD defined for the response of the operation, which contains the XSD of Employee class. So I copied this XSD and pasted it in an XSD on my local disk at c:/Temp/Employees.xsd

Using the visual studio command line I can generate a c# class from this xsd:

WCF REST service generate data contract

As you can see it writes a class employees.cs to the directory where I executed it. I imported this class into my project and changed 1 little detail:

WCF REST Service DataContractAttribute

I’ve had to add the DataContractAttribute to the Employee class with the namespace manually, if I want to use this with the DataContractSerializer, otherwise it will fail.

Adding an employee from our client:

WCF REST service client invoking operations DataContractSerializer

4. What about also support ATOM format next to our JSON/XML in the same operation

To also support ATOM format in our GetEmployees() operation, next to the JSON and XML format, you can find more in this blog post of mine, just handling the ATOM format and the Syndication feed:
WCF REST service operation with JSON and XML also supporting ATOM syndication feed format

You can also find more information about WCF REST services with the OData, Open Data Protocol:
WCF REST service with ODATA and Entity Framework with client context, custom operations and operation interceptors

Some minor changes and some extra code to our operation is needed to also support the ATOM response format, but it is possible within the same operation.

You can also find more information on building REST services with ASP.NET Web API:
Building and consuming REST services with ASP.NET Web API and OData support 

Any suggestions, remarks or improvements are always welcome.
If you found this information useful, make sure to support me by leaving a comment.

Cheers and have fun,

Robbin

By Robbin Cremers Posted in WCF Tagged ,

28 comments on “WCF REST service with XML / JSON response format according to Content-Type header

  1. Just found your blogs on the WCF REST services and it’s great information. You don’t happen to have the projects you’ve used available for download do you?

  2. Thanks for the wonderful post.
    Any idea how to return dynamic field from the employee class? Means fields like last name are not predefined.

  3. Good post. I created a similar application and now i want to handle exceptions being thrown from service and it should be handled well. Could you please share the approach if you have? I tried setting OutgoingWebResponseContext but i am getting HTTP 400 Not found always.

  4. Great article Robbin – I knew there had to be a fairly easy way to set a default content type without expecting the client to set the content-type for every request.

  5. Hi, i have written vbscript in QTP for rest service. I am getting response, but it is not in XML format, getting in json format. Can any one help me how to get response in XML format.

    • Set the DefaultOutgoingResponseFormat in your web.config to set the default outgoing response format to XML. If you want to set the response format to XML for a certain method, you can set the ResponseFormat (or something like it) in the WebInvoke or WebGet attribute and set the value to XML.

  6. Hi, Your post was really good.
    Can the same be used for a https enabled wcf service with REST.
    Does it require any modifications.
    If so can you please help on that with a sample

  7. Hi, Slight more additional requirement Robert.
    Is it possible to retrieve a Json Object from the https federated service i.e; Binding is ws2007HttpFederated Binding and I need to consume that object in JavaScript or winJs.

    If it is possible can you please guide me in the way it should be done

    Thanks in advance
    Regards
    Tejaswi

  8. Pingback: What is RESful service and designning RESTful service using ASP.NET | Broken Code

  9. Hi !! Excellent post ! I am doin a WCF Rest but I am getting this error : Bad Request 400 in Flidder and web,
    this is my source:

    [WebInvoke(Method = "POST", UriTemplate = "CreateFlight", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped ), Description("Method for add new Plan ")]
    [OperationContract]
    FlightPlan CreateFlightPlan(FlightPlan FlightCrear);
    I tried to fix but still .. can you help please
    Thanks!!

    kind regards

  10. Pingback: 推荐2篇关于创建和调用 RESTFul WCF Service方面的文章 | EntLib.net 技术分享平台

  11. Hi Friend
    i am getting blank page once i request the webget and webinvoke method
    but in RestServices.svc
    public List GetEmployees()
    {
    //foreach (Employee ep in EmployeeRepository.Employees())
    //{
    // Console.Write(ep.Ln);
    // Console.ReadLine();
    //}
    return EmployeeRepository.Employees();
    }
    it returns i check as above code
    but i am not getting what i missed
    Please Help me

    web config
    ———————————–

  12. Pingback: WCF REST service with XML / JSON response format according to Content-Type header | ИТ Блог

  13. Hi, Thanks for the detailed writeup. This has been very helpful indeed.
    We have a WCF REST service and we have tagged all the API’s with “ResponseFormat = WebMessageFormat.Json”
    However when we try to use the automatically generated help page it spits out XML and JSON both.
    I have tried the following in the web.config:

    but the help page still lists XML and JSON.
    Is there a way to disable XML in the help?

    Thanks!!

  14. Web config settings:
    webHttp helpEnabled=”true” automaticFormatSelectionEnabled=”false” defaultOutgoingResponseFormat=”Json”

    Sorry, didn’t show up in the previous post.

  15. Hello,
    I trried your example and I have “Cannot process the message because the content type ‘application/json’ was not the expected type ‘text/xml; charset=utf-8′”.

    Have yout got a solution.

    Before I change the structure of the project, it worked well.

    Thanks

  16. Hello Robbin,
    I absolutely loved the way you explained WCF REST service and appreciate the fact that you used an example to explain the service and its implementation.(This explanation was much easier to grasp for a novice like me! )
    I built a WCF REST service myself and implemented much of your example in my own project.
    My GET worked well on both fiddler and localhost.
    But when I tried debugging my method AddEmployee using fiddler I get an exception that says “Object reference not set to an instance of an object”
    Apparently,the instance employee has the value of null once passed as a parameter to the method.So I get an NullReference exception everytime I try using it in the method.
    I have tried a lot of things but nothing has worked so far.
    Its been over 2 days i have been stuck with this.So you’re probably my last hope of finding a solution.
    Any help would be much appreciated.
    Thank you for your time.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s