Welcome to MSDN Blogs Sign in | Join | Help
How to consume REST services with WCF

As you are probably aware by now, Windows Communication Foundation (WCF) 3.5 introduced a new binding called WebHttpBinding to create and to consume REST based services. If you are new to the WCF Web Programming model then see here for more details.

There have been many articles and blogs on how to host a RESTful service. However there doesn’t seem to be much written work on how to consume these services so I thought to write a few lines on this topic.

The new WebHttpBinding is used to configure endpoints that are exposed through HTTP requests instead of SOAP messages. So you can simply call into a service by using a URI.  The URI usually includes segments that are converted into parameters for the service operation.

So the client of a service of this type requires 2 abilities: (1) Send an HTTP request, (2) Parse the response. The default response message format supported out of the box with the WebHttpBinding is “Plain old XML” (POX). It also supports JSON and raw binary data using the WebMessageEncodingBindingElement.

One way of consuming these services is by manually creating a HTTP request. The following example is consuming the ListInteresting operation from Flickr:

WebRequest request = WebRequest.Create("http://api.flickr.com/services/rest/?method=flickr.interestingness.getList&api_key=*&extras=");

WebResponse ws = request.GetResponse();

XmlSerializer s = new XmlSerializer(typeof(PhotoCollection));

PhotoCollection photos = (PhotoCollection)s.Deserialize(ws.GetResponseStream());

The idea is simple:

-          Do the HTTP request and include all the parameters as part of the URI

-          Get the response that is in XML format

-          Either parse it or deserialize it into an object

The above code works but it is not elegant: We are not using the unified programming model offered by WCF and the URL is hacked together using string concatenation. The response is also manually deserialized into an object. With WCF and the WebHttpBinding we can automate most of this.

The first step is to define our service contract:

[ServiceContract]

[XmlSerializerFormat]

public interface IFlickrApi

{

  [OperationContract]

  [WebGet(

      BodyStyle = WebMessageBodyStyle.Bare,

      ResponseFormat = WebMessageFormat.Xml,

      UriTemplate = "?method=flickr.interestingness.getList&api_key={apiKey}&extras={extras}")]

  PhotoCollection ListInteresting(string apiKey, string extras);

}

As you can see, I am specifically instructing WCF to use the XML Serializer Formatter for this. The next step is to set the client endpoint. I decided to do this inside the config file:

<system.serviceModel>

  <client>

    <endpoint address="http://api.flickr.com/services/rest"

              binding="webHttpBinding"

              behaviorConfiguration="flickr"

              contract="FlickrApp.IFlickrApi"

              name="FlickrREST" />

  </client>

 

  <behaviors>

    <endpointBehaviors>

      <behavior name="flickr">

        <webHttp/>

      </behavior>

    </endpointBehaviors>

  </behaviors>


In order to be able to use the XML Serializer Formatter, I need XML Serializable types:

  [XmlRoot("photos")]

  public class PhotoCollection

  {

    [XmlAttribute("page")]

    public int Page { get; set; }

 

    ...

 

    [XmlElement("photo")]

    public Photo[] Photos { get; set; }

 

  }

 

  public class Photo

  {

    [XmlAttribute("id")]

    public string Id { get; set; }

 

    [XmlAttribute("title")]

    public string Title { get; set; }

 

    ...

  }

The final step is to create an instance of the client proxy:

ChannelFactory<IFlickrApi> factory =

  new ChannelFactory<IFlickrApi>("FlickrREST");

var proxy = factory.CreateChannel();

var response = proxy.ListInteresting("xxxx", "yyyy");

((IDisposable)proxy).Dispose();

If you don’t like using ChannelFactory directly then you can create your proxy by deriving from ClientBase<>:

public partial class FlickrClient :

  ClientBase<IFlickrApi>, IFlickrApi

{

  public FlickrClient()

  {

  }

 

  public FlickrClient(string endpointConfigurationName) :

    base(endpointConfigurationName)

  {

  }

 

  public FlickrClient(

    string endpointConfigurationName,

    string remoteAddress) :

    base(endpointConfigurationName, remoteAddress)

  {

  }

 

  public FlickrClient(string endpointConfigurationName,

    EndpointAddress remoteAddress) :

    base(endpointConfigurationName, remoteAddress)

  {

  }

 

  public FlickrClient(Binding binding,

    EndpointAddress remoteAddress) :

    base(binding, remoteAddress)

  {

  }

 

  public PhotoCollection ListInteresting(string apiKey, string extras)

  {

    return base.Channel.ListInteresting(extras);

  }

}

Now the client code will look similar to the following:

FlickrClient proxy = new FlickrClient();

var response = proxy.ListInteresting("xxxxxx","yyyyyy");

((IDisposable)proxy).Dispose();

 

Hope the above helps.

Posted: Monday, April 21, 2008 5:55 PM by pedramr
Filed under:

Comments

mhsimkin said:

Pedram, great posting.  A quick question.  Is there a way to consume a JSON based REST service?

Thanks

Marc

# April 24, 2008 12:58 PM

harishpa said:

This is good stuff . I was going to do this myself to see how this would work ..!!

# May 2, 2008 2:29 PM

A Connected World through Software Architecture - Harry Pavithran said:

&#160; I thought I would do some research on REST and I think this link&#160; http://www.xfront.com/REST-Web-Services.html

# May 17, 2008 12:03 AM

John said:

Hi Pedram!  Thanks for the info.  There's a bug though - you have an endpointBehavior configured, but your endpoint is not referring to it.  You need to add 'behaviorConfiguration="flickr"' to the endpoint.  This is something I keep forgetting to do myself!

# June 11, 2008 6:21 PM

Navin said:

Can we invoke REST services asynchronously?

# June 12, 2008 12:45 AM

jillzhang said:

very good,thank you for your share

# July 10, 2008 3:53 AM

jillzhang said:

i have a problem

when i call wcf method from extjs cross domain ,the response format can not adapt ,because it is either json or xml,neither is <script></script> format,it is perfect if wcf can response a cleartext format!

# July 10, 2008 3:57 AM

TrackBack said:

# July 10, 2008 7:52 PM

TrackBack said:

# July 10, 2008 7:52 PM

Re ultram. said:

Ultram. Buy ultram cheapest site. Buy ultram. Ultram ortho mcneil.

# August 26, 2008 5:25 AM

John Fitzpatrick said:

This was very helpful. I was using HttpWebRequest for REST and WCF for SOAP and of course it wasn't unified. I hadn't thought of doing it this way.

Thanks

# September 18, 2008 12:57 PM

Jose Manuel said:

Hello! I've read you article lots of times, but I don't understand any of those app.config settings. I really would like to use REST services from Community Server. I've got the documented REST API, but I need a little help. Please check it out:

http://api.communityserver.org/

I'm very interested in the blogs section. It uses headers for authentication.

I can donate money if you help me. Thanks!

I'll follow your blog .

# October 13, 2008 11:12 AM

Outsourcing to Sleestak said:

&#160; This past Saturday was the Atlanta Code Camp.&#160; I want to be make a point of thanking Cliff

# March 15, 2009 5:11 PM

Outsourcing to Sleestak said:

Ingredients: Visual Studio 2008 SP1 (C#), WCF REST Starter Kit Preview 2 In Preview 1 of the WCF REST

# March 18, 2009 6:30 PM

keith said:

great article, very helpful - thanks!

# August 13, 2009 6:21 AM

Jochen said:

I find this example somehow funny: In the first few paragraphs you are showing a perfectly fine way to interact with an HTTP server and it only takes 4 lines of code.

And then you are proposing something that takes tons of additional boilerplate code, requires lots of setup and is less flexible than just consuming the XML.

That makes no sense to me whatsoever.

# October 29, 2009 2:07 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

  
Enter Code Here: Required

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Page view tracker