How to consume REST services with WCF

How to consume REST services with WCF

Rate This
  • Comments 29

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.

Leave a Comment
  • Please add 8 and 4 and type the answer here:
  • Post
  • PingBack from http://microsoftnews.askpcdoc.com/?p=3505

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

    Thanks

    Marc

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

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

  • 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!

  • Can we invoke REST services asynchronously?

  • very good,thank you for your share

  • 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!

  • 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

  • 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 .

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

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

  • great article, very helpful - thanks!

Page 1 of 2 (29 items) 12