The Imaginative Universal

Studies in Virtual Phenomenology -- @jamesashley

WCF REST Starter Kit 2: Calling Twitter

March 20
by James Ashley 20. March 2009 18:01

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.

Tags: , , ,

Recipe | Starter Kit | Tutorial | WCF REST