Archive for October 8, 2011

REST/HTTP Services in WCF is nothing new, it’s been there since 2008, version 3.5 of the framework. Yesterday I came across a question that whether a particular operation can support both XML/JSON format and return response in the suitable format as demanded by the client program. To my knowledge the answer was a both Yes & No. Because I did quite extensive study of the System.ServiceModel.Web.WebHttpBehavior and System.ServiceModel.Web.WebGetAttribute back in 2008 as given in the post below:

https://sankarsan.wordpress.com/2008/10/28/wcf-web-model-poxjson-support/

This limitation drew my attention. However there was a solution to the problem.We can always extend the WebHttpBehavior and override the WebHttpBehavior.GetReplyDispatchFormatter method to return our own custom implementation of System.ServiceModel.Dispatcher.IDispatchFormatter. A similar implementation can be found in the post below:

http://damianblog.com/2008/10/31/wcf-rest-dynamic-response/

Wait …..

This kind of an implementation is actually now part of the .NET 4.0. This is controlled by the automaticFormatSelectionEnabled property of the WebHttpBehavior. This property when set to true then the response format of the operation is governed by the Accept , Content-Type header of the request. This feature is called Automatic Format Selection. This is what we will discuss in this post.

I have a simple service with a Add operation as shown below:

[OperationContract] 
[WebGet] 
public int  Add(int i , int j) 
{ 
   // Add your operation implementation here 
   return i+j; 
} 

The client code is a .NET program sending a HTTP request as shown below:

HttpWebRequest request = HttpWebRequest.Create("http://localhost:5072/TestService.svc/Add?i=1&j=1") as HttpWebRequest; 
request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.None; 
request.Method = "GET"; 
request.ContentType = "text/xml"; 
request.Accept = "text/xml"; 
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
using (StreamReader rdr = new StreamReader(response.GetResponseStream())) 
{ 
    Console.WriteLine(rdr.ReadToEnd()); 
}

The response is in JSON format as shown below:

{"d":2}

Now I will turn on auto format selection as shown below using config.

wcfauto

Now the output is XML as shown below:

<AddResponse xmlns="http://sankarsanbose.com/test"><AddResult>2</AddResult></Add 
Response>

Now I will change the Accept header to JSON.

request.ContentType = "text/xml"; 
request.Accept = "text/json";

The response is now again in JSON format as shown below:

{"d":2}

NOTE: If both Accept and Content-Type are specified then Accept takes the higher priority.

What happens if I set the response format in WebGetAttribute? Say I make it Json as shown below:

[OperationContract] 
        [WebGet(ResponseFormat=WebMessageFormat.Json)] 
        public int  Add(int i , int j) 
        { 
            // Add your operation implementation here 
            return i+j; 
        }

The output is driven by Accept Header and is in XML format

<AddResponse xmlns="http://sankarsanbose.com/test"><AddResult>2</AddResult></Add 
Response> 

If I change the headers to JSON obviously the output is JSON.

Now I am changing the ResponseFormat to XML as shown below:

[WebGet(ResponseFormat=WebMessageFormat.Xml)] 

The request headers are set as shown below:

request.ContentType = "text/json"; 
request.Accept = "text/json"; 

The output surprisingly is just 2 neither JSON nor XML.

The request headers are changed back to XML

request.ContentType = "text/xml";
request.Accept = "text/xml";

Now the output is XML is as shown below:

 
<int xmlns="http://schemas.microsoft.com/2003/10/Serialization/">2</int>

This is clearly different from structure of the XML generated earlier. Seems to be using the different serializer.

I was not able to articulate the reason for the above two anomalies very clearly. But I think when auto format selection is enabled then providing the ResponseFormat does not make much sense.