WCF REST Starter Kit 2: Calling Twitter

The great power of the WCF REST starter Kit comes from allowing programmers to easily call pre-existing REST services written on non-Microsoft platforms.  Of those, Twitter is probably the most popular and easiest to understand.  In order to use twitter, we need at a bare minimum to be able to read tweets, to write tweets, and occasionally to delete a tweet.  Doing this also showcases the core structure of REST calls: they allow us to perform CRUD operations using the following web methods: GET, POST, PUT and DELETE.

The following example will use GET to read tweets, POST to insert tweets, and DELETE to remove tweets.

Ingredients: Visual Studio 2008 SP1 (C#), WCF REST Starter Kit Preview 2, a Twitter account

Sample: download (10 KB)

In this tutorial, I will walk you through building a simple Twitter command line application — I know, I know, Twitter from a console is what we’ve all been longing for!

This tutorial will use the techniques from the previous Getting Started post on WCF REST and expand on them to develop a “real world” application.

The first stop is the documentation on the Twitter API, which can be found here.  Based on the documentation, we can see that we want to call the friends_timeline resource in order to keep up with our twitter buddies.  We will want the update resource in order to insert new tweets.  We will also want the destroy resource so we can immediately delete tweets like “I am testing my console app”, “testing again”, “still testing 3”, etc.

Reading our friends’ tweets is the easiest part of all this.  The basic code looks like this:

var client = new HttpClient();

 

//set authentication credential

NetworkCredential cred = new NetworkCredential(_userName, _password);

client.TransportSettings.Credentials = cred;

 

//set page parameter

var queryString = new HttpQueryString();

queryString.Add(“page”, page.ToString());

 

//call Twitter service

var response =

        client.Get(

        new Uri(“http://twitter.com/statuses/friends_timeline.xml”)

        , queryString);

 

var statuses = response.Content.ReadAsXmlSerializable<statuses>();

foreach (statusesStatus status in statuses.status)

{

    Console.WriteLine(string.Format(“{0}: {1}”

        , status.user.name

        , status.text));

    Console.WriteLine();

    Console.WriteLine();

}

Twitter uses basic authentication to identify users.  To insert this information into our header, we create a new Network Credential and just inject it into our HttpClient instance.  (_userName and _password are simply private static fields I created as placeholders.)  The service can also take a “page” parameter that identifies which page of our friends’ statuses we want to view.  This code uses the HttpQueryString type that comes with the Starter Kit to append this information.

The results should look something like this:

console4

Probably the trickiest thing in getting this up and running is using Paste XML as Types from the Edit menu in order to generate the statuses class for deserialization.  To get the raw XML, you will need to browse to http://twitter.com/statuses/friends_timeline.xml, at which point you will be prompted for your Twitter account name and password.  In my case, I then copied everything out of the browser and pasted it into notepad.  I then stripped out the XML declaration, as well as all the hyphens that IE puts in for readability.  Having too many status elements turned out to make Visual Studio cry, so I removed almost all of them leaving only two.  Leaving two turned out to be important, because this allowed the underlying Paste XML as Types code to know that we were dealing with an array of status elements and to generate our classes appropriately.  At the end of this exercise, I had a statuses class, statusesStatus, statusesStatusUser, and a few others.

Posting a twitter status is a little bit harder, partly due to the way the Twitter API implements it.  Here’s the basic code for that:

var client = new HttpClient();

 

//set authentication credential

NetworkCredential cred = new NetworkCredential(_userName, _password);

client.TransportSettings.Credentials = cred;

 

//fix weird twitter problem

System.Net.ServicePointManager.Expect100Continue = false;

 

//send update

if (p.Length > 140) p = p.Substring(0, 140);

HttpContent body = HttpContent.Create(string.Format(“status={0}&source={1}”

    , HttpUtility.UrlEncode(p)

    , “CommandLineTwitterer”)

    , Encoding.UTF8

    , “application/x-www-form-urlencoded”);

 

var response = client.Post(“http://twitter.com/statuses/update.xml”, body);

Console.WriteLine(“Your tweet was twutted successfully.”);

This took a bit of trial and error to figure out, and in the end I just opened my Twitter home page with the Web Development Helper to see what the message was supposed to look like.  The Expect100Continue is needed to handle a change in Twitter’s API that showed up sometime at the beginning of the year, and which is explained here, here and here.

In order to make delete workable in a console application, I have tacked the following lines of code to the end of the status update method:

var status = response.Content.ReadAsXmlSerializable<status>();

_lastTweetId = status.id;

which hangs onto the id of the successful tweet so the user can turn around and perform a DESTROY command in order to delete the previous tweet.

 

You will notice that in the above snippet, I am using a type called status instead of one the objects associated with statuses from the simple GET service call above.  It is actually identical to the statusesStatus type above.  I gen-ed the status class out of the response simply because I needed a class called “status” in order to map the XML element returned to a clr type.  An alternative way to do this is to add an XmlRoot attribute to the statusesStatus class in order to make the serialization work properly:

 

[System.Xml.Serialization.XmlRoot(“status”)]

public partial class statusesStatus

{

    …

This would allow us to write our deserialize code like this:

var status = response.Content.ReadAsXmlSerializable<statusesStatus>();

_lastTweetId = status.id;

The delete code finishes off this recipe since it will demonstrate using one of the methods one rarely sees in typical REST examples (the other being PUT) .  It looks like this:

 

if (_lastTweetId == 0)

    return;

 

HttpClient client = new HttpClient();

 

//set authentication credential

NetworkCredential cred = new NetworkCredential(_userName, _password);

client.TransportSettings.Credentials = cred;

HttpResponseMessage response = null;

response = client.Delete(

    string.Format(“http://twitter.com/statuses/destroy/{0}.xml”

        , _lastTweetId)

    );

In order to pull this all together and have a functioning app, you just need a simple processing method.  The main processing code here that interprets commands and calls the appropriate methods simply loops until the EXIT command is called:

static void Main(string[] args)

{

    if (!CheckArgsForCredentials(args))

        SetCredentials();

 

    var input = string.Empty;

    while (input.ToUpper() != “EXIT”)

    {

        input = ProcessInput(Console.ReadLine());

    }

}

 

private static string ProcessInput(string input)

{

    //INPUT = READ

    if (input.ToUpper().IndexOf(“READ”) > -1)

    {

        if (input.ToUpper().IndexOf(“PAGE”) > -1)

        {

            var iPage = GetPageNumber(input);

            ReadFriendsTimeline(iPage);

        }

        else if (input.ToUpper().IndexOf(“ME”) > -1)

        {

            ReadUserTimeline();

        }

        else

            ReadFriendsTimeline(1);

 

    }

    //INPUT = TWEET

    else if (input.ToUpper().IndexOf(“TWEET”) > -1)

    {

        UpdateTwitterStatus(input.Substring(5).Trim());

    }

    //INPUT = DESTROY

    else if (input.ToUpper().IndexOf(“DESTROY”) > -1)

    {

        DestroyLastTweet();

    }

    return input;

}

This should give you everything you need to cobble together a simple Twitter client using the WCF REST Starter Kit.  Mention should be made of Aaron Skonnard’s excellent blog. After spending half a day on this I discovered that Aaron Skonnard had already written a much more succinct and elegant example of calling Twitter using the HttpClient.  I also found this cool example from Kirk Evans’s blog explaining how to accomplish the same thing using WCF without the HttpClient.

The full source code (10K) for this sample app has the properly generated types for deserialization as well as exception handling and status code handling, in case you run into any problems.  In order to run it, you will just need to add in the pertinent assemblies from the WCF REST Starter Kit Preview 2.

Getting Started with the WCF REST Starter Kit Preview 2 HttpClient

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

In Preview 1 of the WCF REST Starter Kit, Microsoft provided many useful tools for building RESTful services using WCF.  Missing from those bits was a clean way to call REST services from the client.  In Preview 2, which was released on March 13th, this has been made up for with the HttpClient class and an add-in for the Visual Studio IDE called Paste XML as Types.

The following getting-started tutorial will demonstrate how to use the HttpClient class to call a simple RESTful service (in fact, we will use the default implementation generated by the POX service template).  If you haven’t downloaded and installed the WCF REST Starter Kit, yet, you can get Preview 2 here. You can read more about the Starter Kit on Ron Jacobs’ site.

The sample solution will include two projects, one for the client and one for the service. 

1. Start by creating a Console Application project and solution called RESTfulClient.

2. Add a new project to the RESTfulClient solution using the Http Plain XML WCF Service project template that was installed when you installed the Starter Kit.  Call your new project POXService. 

The most obvious value-added features of the WCF REST Starter Kit are the various new project templates that are installed to make writing RESTful services easier.  Besides the Http Plain XML WCF Service template, we also get the ATOM Publishing Protocol WCF Service, the ATOM Feed WCF Service, REST Collection WCF Service, REST Singleton WCF Service and good ol’ WCF Service Application.

PoxService 

For this recipe, we will just use the default service as it is. 

[WebHelp(Comment = “Sample description for GetData”)]

[WebGet(UriTemplate = “GetData?param1={i}&param2={s}”)]

[OperationContract]

public SampleResponseBody GetData(int i, string s)

{

 

   return new SampleResponseBody()

   {

     Value = String.Format(“Sample GetData response:”   {0}’, ‘{1}'”, i, s)

   };

}

For the most part, this is a pretty straightforward WCF Service Method.  There are some interesting additional elements, however, which are required to make the service REST-y.

(In a major break with convention, you will notice that the default service created by this template is called Service rather than Service1.  I, for one, welcome this change from our new insect overlords.)

The WebGet attribute, for instance, allows us to turn our service method into a REST resource accessed using the GET method.  The UriTemplate attribute parameter specifies the partial Uri for our resource, in this case GetData.  We also specify in the UriTemplate how parameters can be passed to our resource.  In this case, we will be using a query string to pass two parameters, param1 and param2.

By default, the template provides a Help resource for our service, accessed by going to http://localhost:<port>/Service.svc/Help .  It will automatically include a description of the structure of our service.  The WebHelp attribute allows us to add further notes about the GetData resource to the Help resource.

You will also notice that the GetData service method returns a SampleResponseBody object.  This is intended to make it explicit in our design that we are not making RPC’s.  Instead, we are receiving and returning messages (or documents, if you prefer).  In this case, the message we return is simply the serialized version of SimpleResponseBody, which is a custom type that is specified in the service.svc.cs file and which does not inherit from any other type.

public class SampleResponseBody
{
    public string Value { get; set; }
}

3. Right click on the PoxService project and select Debug | Start New Instance to see what our RESTful service looks like.  To see what the service does, you can browse to http://localhost:<port>/Service.svc/Help .  To see what the schema for our GetData resouce looks like, go to http://localhost:<port>/Service.svc/help/GetData/response/schema .  Finally, if you want to go ahead and call the GetData service, browse to http://localhost:<port>/Service.svc/GetData .

(In the rest of this tutorial, I will simply use  port 1300, with the understanding that you can specify your own port in the code.  By default, Visual Studio will randomly pick a port for you.  If you want to specify a particular port, however, you can go into the project properties of the PoxService project and select a specific port in the project properties Web tab.)

<SampleResponseBody xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Value>Sample GetData response: '0', ''</Value> 
</SampleResponseBody>

4. Go to the RESTfulClient project and add a new class called SampleResponseBody.  We are going to create a type for deserializing our SampleResponseBody XML element.  We could write out the class by hand, and prior to Preview 2 we probably would have had to.  It is no longer necessary, however.  If you copy the XML returned from browsing our resource (you may need to use View Source in your browser to get a clean representation) at http://localhost:1300/Service.svc/GetData you can simply paste this into our SampleResponseBody.cs file by going to the Visual Studio Edit menu and selecting Paste XML to Types.  To get all the necessary types in one blow, you can also go to http://localhost:1300/Service.svc/Help and use Paste XML to Types.  As a third alternative, just copy the XML above and try Paste XML to Types in your SampleResponseBody class.  However you decide to do it, you are now in a position to translate XML into CLR types.

Your generated class should look like this:

[System.CodeDom.Compiler.GeneratedCodeAttribute(“System.Xml”, “2.0.50727.3053”)]

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]

[System.Xml.Serialization.XmlRootAttribute(Namespace = “”, IsNullable = false)]

public partial class SampleResponseBody

{

 

        private string valueField;

 

        /// <remarks/>

        public string Value

        {

            get

            {

                return this.valueField;

            }

            set

            {

                this.valueField = value;

            }

        }

}

 

5.  Next, we need to add the Starter Kit assemblies to our console application.  The default location for these assemblies is C:\Program Files\Microsoft WCF REST\WCF REST Starter Kit Preview 2\Assemblies .  The two assemblies we need for the client are Microsoft.Http.dll and Microsoft.Http.Extensions.dll .  (I happen to like to copy CodePlex bits like these into a folder in the My Documents\Visual Studio 2008 directory, to make it relatively easier to track drop versions).

6. We will now finally add some code to call call our GetData resource using the HttpClient class.  The following code will simply prompt the user to hit {Enter} to call the resource.  It will then return the deserialized message from the resource and prompt the user to hit {Enter} again.  Add the following using references to your Program.cs file:

using Microsoft.Http;

using System.Xml.Serialization;

  Now place the following code in the Main() method of Program.cs:

static void Main(string[] args)

{

    Console.WriteLine(“Press {enter} to call service:”);

    Console.ReadLine();

 

    var client = new HttpClient(http://localhost:1300/Service.svc/);

    HttpResponseMessage response = client.Get(“GetData”);

 

    var b = response.Content.ReadAsXmlSerializable<SampleResponseBody>();

 

    Console.WriteLine(b.Value);

    Console.ReadLine();

}

Both the Get request and the deserialization are simple.  We pass a base address for our service to the HttpClient constructor.  We then call the HttpClient’s Get method and pass the path to the resource we want (in true REST idiom, PUT, DELETE and POST are some additional methods on HttpClient).

The deserialization, in turn, only requires one line of code.  We call the Content property of the HttpResponseMessage instance returned by Get() to retrieve an HttpContent instance, then call its generic ReadAsXmlSerializable method to deserialize the XML message into our SampleResponseBody type.

While you could previously do this using WCF and deserialization, or even the HttpWebRequest and HttpWebResponse types and an XML parser, this is significantly easier.

 

console1

 

7. If you recall, the signature of the GetData service method actually takes two parameters, an integer and a string.  When translated into a REST resource, the parameters are passed in a query string.  To complete this example, we might want to go ahead and pass these parameters to our GetData resource.  To do so, replace the code above with the following:

static void Main(string[] args)

{

    Console.WriteLine(“Enter a number:”);

    int myInt;

    Int32.TryParse(Console.ReadLine(), out myInt);

 

    Console.WriteLine(“Enter a string:”);

    var myString = Console.ReadLine();

 

    var q = new HttpQueryString();

    q.Add(“param1”, myInt.ToString());

    q.Add(“param2”, myString);

 

    var client = new HttpClient(“http://localhost:1300/Service.svc/”);

    HttpResponseMessage response = client.Get(new Uri(client.BaseAddress + “GetData”), q);

    var b = response.Content.ReadAsXmlSerializable<SampleResponseBody>();

 

    Console.WriteLine(b.Value);

    Console.WriteLine(“Press {enter} to end.”);

    Console.ReadLine();

}

The first block asks for a number and we verify that a number was indeed submitted.  The next block requests a string.

The third block creates an HttpQueryString instance using our console inputs.

The important code is in the fourth block.  You will notice that we use a different overload for the Get method this time.  It turns out that the only overload that accepts a query string requires a Uri for its first parameter rather than a partial Uri string.  To keep things simple, I’ve simply concatenated “GetData” with the BaseAddress we previously passed in the constructor (this does not overwrite the BaseAddress, in case you were wondering).  We could have also simply performed a string concatenation like this, of course:

HttpResponseMessage response =

client.Get(string.Format(“GetData?param1={0}&param2={1}”,myInt.ToString(), myString));

but using the HttpQueryString type strikes me as being somewhat cleaner. 

If you run the console app now, it should look something like this:

console2

 

And that’s how we do RESTful WCF as of Friday, March 13th, 2009. 

To see how we used to do it prior to March 13th, please see this excellent blog post by Pedram Rezai from April of last year.