Building a REST client with WCF

Wednesday, November 12 2008

Microsoft recently released a WCF and REST starter kit on Codeplex. The kit provides a library of helper classes and extension methods for building a REST service, as well as several project templates which will take a lot of the work out of setting up the plumbing. They've enlisted the help of Pluralsight's Aaron Skonnard to provide some guidance which he does in a blog post, whitepaper and series of screencasts. There's some great info there, and it's well worth a look.

What I haven't seen is a lot of coverage is how to consume REST services using WCF. If you watch the screencasts, Aaron uses Fiddler to POST and PUT the resources on the service side. This is great as it shows you what is happening over the wire, but it doesn't help you if you're trying to call a service from your code.

So I've put together a very basic REST service and client as an example to build from.

The service is based on the WCF REST Collection Service template which is added to your Visual Studio templates when you install the starter kit.

resttemplates

 

To make this compile, you'll also need to compile the Microsoft.ServiceModel.Web component source which should be in Program Files\WCF REST Starter Kit\Microsoft.ServiceModel.Web. To do this, you'll also need SP1 of .NET 3.5 and Visual Studio 2008 installed.

I didn't change much from the sample template implementation, I replaced their "SampleItem" class and replaced it with my own "Stock" class and added a few sample values to the initial collection via a constructor.

The end result is a simple REST service that lists some "Stock" data (Name, Symbol, Price) and lets you GET a collection or individual item, POST a new stock ticker and values, and update (PUT) any of the existing ones.

The collection results are wrapped in a StockInfo XML node containing the item as well as an EditLink node with the URI for the resource.

servicexml

I won't dwell to much more on the server side of this as the screencasts do a great job, but I will talk through building a client to consume this service.

Building a simple WCF REST Client

The first thing you need to do is reference the System.ServiceModel and System.ServiceModel.Web assemblies. The System.ServiceModel assembly is the heart of all WCF applications, the Web assembly is new to .NET 3.5 and provides classes for what they call the "web programming model".

Next we create an interface for our client, this defines the Service Contract we will be working with. The interface looks like this :

 

01.[ServiceContract]
02.    public interface IStockClient
03.    {
04.        [OperationContract]
05.        [WebGet(
06.            BodyStyle = WebMessageBodyStyle.Bare,
07.            ResponseFormat = WebMessageFormat.Xml,
08.            UriTemplate = ""
09.            )]
10.        StockList GetAllStocks();
11. 
12.        [OperationContract]
13.        [WebGet(
14.            BodyStyle = WebMessageBodyStyle.Bare,
15.            ResponseFormat = WebMessageFormat.Xml,
16.            UriTemplate = "{symbol}"
17.            )]
18.        Stock GetStock(string symbol);
19. 
20.        [OperationContract]
21.        [WebInvoke(
22.            Method = "PUT",
23.            BodyStyle = WebMessageBodyStyle.Bare,
24.            ResponseFormat = WebMessageFormat.Xml,
25.            UriTemplate = "{symbol}"
26.            )]
27.        Stock UpdateStock(string symbol, Stock stock);
28. 
29.        [OperationContract]
30.        [WebInvoke(
31.            Method = "POST",
32.            BodyStyle = WebMessageBodyStyle.Bare,
33.            ResponseFormat = WebMessageFormat.Xml,
34.            UriTemplate = ""
35.            )]
36.        StockInfo AddStock(Stock stock);
37. 
38.    }

Most of this will look familiar if you've done any WCF, but to walk through it :

  • The methods we will be inplementing in our local client are GetAllStocks, GetStock, UpdateStock and AddStock. These method names bear no resemblance to any naming convention on the server side, they are just local methods.
  • The ServiceContract attribute tells WCF that this is what the service implementation is going to look like, and the OperationContract tells WCF this is what methods we can call over the wire.
  • The WebGet and WebInvoke attributes tell WCF how we are going to call these on the service side.

To look a little closer at the last point.

1.[WebGet(
2.    BodyStyle = WebMessageBodyStyle.Bare,
3.    ResponseFormat = WebMessageFormat.Xml,
4.    UriTemplate = ""
5.    )]
  • This attribute says we are going to perform a GET request against the service.
  • The WebMessageBodyStyle.Bare means that the response is going to be just the resource data, and not wrapped in any extraneous metadata.
  • ResponseFormat looks pretty self explanatory, we are going to get our data back as XML. Another option here is JSON.
  • UrITemplate defines the location of the resource. As it's blank, we will be performing a GET against the base URI of the service (defined in the configuration, in this case it's http://127.0.0.1:16353/Service.svc/). In the GetStock and UpdateStock methods you'll see that the template is marked up with the name of one of the method parameters, i.e. {symbol}. This means that the call will be made to a URI such as http://127.0.0.1:16353/Service.svc/MSFT.

In some of the other methods, you'll see this decoration as a WebInvoke instead of WebGet. This attribute means that instead of a GET, we are going to perform an HTTP PUT or POST against the service.

That's a big part of the work done there, next we have to provide the implementation of this interface, which in this case is very simple. The WCF libraries do most of the work.

01.public class StockClient : ClientBase<istockclient>, IStockClient    
02.{        
03.    public StockList GetAllStocks()        
04.    {            
05.        return this.Channel.GetAllStocks();        
06.    }        
07.    public Stock GetStock(string symbol)        
08.    {            
09.        return this.Channel.GetStock(symbol);        
10.    }        
11.    public Stock UpdateStock(string symbol, Stock stock)        
12.    {            
13.        return this.Channel.UpdateStock(symbol, stock);        
14.    }        
15.    public StockInfo AddStock(Stock stock)        
16.    {            
17.        return this.Channel.AddStock(stock);        
18.    }    
19.}

 

You'll see this inherits from a ClientBase<T> class, and from IStockClient.

We have a few missing pieces here, I have methods returning StockInfo, Stock and StockList. These are some classes I defined to deserialize the XML into, the classes are defined to match the XML returned from the service as showing in the screenshot above.

 

01.[CollectionDataContract(Namespace = "")]
02.public class StockList : List<stockinfo>
03.{
04.}
05. 
06.[DataContract(Namespace = "")]
07.public class StockInfo
08.{
09.    [DataMember]
10.    public Stock Stock { get; set; }
11.    [DataMember]
12.    public string EditLink { get; set; }
13.}
14. 
15.[DataContract(Namespace = "")]
16.public class Stock
17.{
18.    [DataMember]
19.    public string Symbol { get; set; }
20.    [DataMember]
21.    public string Name { get; set; }
22.    [DataMember]
23.    public double Price { get; set; }
24.}

You can see that the classes are decorated as DataContracts, and the members are DataMembers. In this case, I've built the classes to match the XML that is being returned from my service. If I wanted to use a different naming convention in my client, I can use the Name property in the DataContract constructor to match the XML.

The final piece of the puzzle is the configuration. Configuration of WCF is the part that scares most people, this is in part because Visual Studio's generated code adds all of the possible options. The configuration for this is quite simple though.

wcf_config

  • We've defined an endpoint, which is the base address for the service.  It is sitting on an ASP.NET Development Server at http://127.0.0.1:16353/Service.svc/.
  • We're using the webHttpBinding.
  • We have defined a contract in IStockClient and provided a qualified configuration value for that.
  • Finally we've specified a behavior, called "stocks". Below the endpoint configuration we have defined this and placed the webHttp tag.

That's really all there is to it, I haven't implemented any authentication and security in either the service or the client, that might be a topic for a future article. You can download the source here and run it if you like. You'll see I've implemented this inside a simple Console app, so as to not confuse the issue with multiple assemblies, you can run it and see the various methods being called.

WCF is very flexible and powerful, and this comes with the tradeoff of having a vast array of options and configuration choices. I think this seems to scare a lot of people away from adopting WCF or even finding the time to look at it. WCF isn't going away any time soon though, and REST (or REST like) APIs are in vouge at the moment and the two are a very powerful combination so I hope this demystifies a few things for people.

Comments

Tim Bull said on 11.12.2008 at 4:22 PM

Great article and easy to follow. I can see me stealing, I mean borrowing, this code in the future.

Thanks!


Damian said on 11.12.2008 at 4:46 PM

Thanks Tim

Feel free to borrow as much as you like!


Venkat said on 12.08.2008 at 5:30 AM

Great Article.

I tried a simple WCF REST Service which has method to return a message on .net 3.5 SP1 with VS2008 and consume using web application. But I got up to the service part and able to access via URL. But I am unable to build a client using asp.net webapplication by adding a service reference.