Programming Twitter with WCF 3.5
Do you Twitter? If so, this could be of interest for you. If not, maybe you are interested in how to use the Twitter REST API to write own client applications.
Imagine you could just use Twitter from your code like this:
1: TwitterStatusProxy proxy = new TwitterStatusProxy( "username", "password" );
2:
3: // retrieve friends timeline
4: XElement timeline = proxy.GetFriendsTimeline();
5:
6: // do whatever you want to do with the data
I just wrote up a demo for a security talk I gave last friday, using the Twitter API from WCF 3.5. One interesting scenario using Twitter, beside its origin to update the current status of the user, is to integrate the pub/sub system with SMS capabilities into an application. Imagine, you have a bunch of field workers on the road and they could just update status information on ongoing business via the Twitter infrastructure or the way back from the central to the field workers. You receive status information via SMS and are up to date. This scenario is especially interesting in Countries where SMS costs are still high. You have up to 250 SMS per week when using Twitter (in the US, I think there is not this limit). Could be a huge amount of money to spare. Ok, there is of course one drawback, the reliability of the plattform. I have no idea how well it scales if it is under pressure and how often downtimes are. Meanwhile you have an API call to get informed about planned downtime slots.
Anyway, I want to show you how to use Twitter with WCF 3.5. Here we go. Twitters API is almost an authenticated one, this means for most calls you have to authenticate yourself before calling into the API. Therefore I have chosen to always provide a username and password in the constructor of the proxy class. I decided also to use for each category an own proxy implementation. Of course, I created a base class to inherit (similar to ClientBase, less functionality) from and all proxies are using this class. My last decision was not to model data contracts or value objects. I decided just to leave it as an XElement, this has the advantage that anyone is free to provide own mapping objects on top of the proxy.
Here is the generic base proxy class
1: public abstract class TwitterProxyBase<T>
2: {
3: protected T proxy;
4: protected readonly string twitterBaseUri = "https://twitter.com";
5:
6: protected TwitterProxyBase( string username, string password )
7: {
8: this.CreateProxy( username, password );
9: }
10:
11: protected void CreateProxy( string username, string password )
12: {
13: WebHttpBinding binding = new WebHttpBinding();
14: binding.Security.Mode = WebHttpSecurityMode.Transport;
15: binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
16:
17: ChannelFactory<T> channel = new ChannelFactory<T>(
18: binding,
19: this.twitterBaseUri );
20:
21: channel.Endpoint.Behaviors.Add( new WebHttpBehavior() );
22:
23: channel.Credentials.UserName.UserName = username;
24: channel.Credentials.UserName.Password = password;
25:
26: proxy = channel.CreateChannel();
27: }
28: }
No error handling in my code, as I just wrote that one for the demo, you should include Error-handling. From this base class you just have to inherit and write a little proxy helper. In general I'm using the WCF 3.5 WebGet and WebInvoke attributes to decorate the proxy interface. This is how the Status API interface of Twitter looks in WCF decorated. I just shortened the class for more clarity.
1: [ServiceContract]
2: public interface ITwitterStatusXml
3: {
4: // serveral operations missing for clarity
5:
6: [OperationContract]
7: [WebGet( UriTemplate = "/statuses/friends_timeline.xml",
8: BodyStyle = WebMessageBodyStyle.Bare,
9: ResponseFormat = WebMessageFormat.Xml )]
10: XElement GetFriendsTimeline();
11:
12: [OperationContract]
13: [WebGet( UriTemplate = "/statuses/friends_timeline/{screenName}.xml",
14: BodyStyle = WebMessageBodyStyle.Bare,
15: ResponseFormat = WebMessageFormat.Xml )]
16: XElement GetFriendsTimelineByScreenName( string screenName );
17:
18: [OperationContract]
19: [WebInvoke( UriTemplate = "/statuses/update.xml?status={status}",
20: Method = "POST",
21: BodyStyle = WebMessageBodyStyle.Bare,
22: ResponseFormat = WebMessageFormat.Xml )]
23: XElement Update( string status );
24: }
Line 7-10 and 12-16 are demonstrating GET operations on the Twitter contract, where line 18-23 are showing a POST.
Now the proxy inherits the base class and this interface.
1: public class TwitterStatusProxy : TwitterProxyBase<ITwitterStatusXml>, ITwitterStatusXml
2: {
3: public TwitterStatusProxy( string username, string password )
4: : base( username, password )
5: {
6: }
7:
8: #region ITwitterStatusXml Members
9:
10: // most operations not included for more clarity
11:
12: public XElement GetFriendsTimeline()
13: {
14: return proxy.GetFriendsTimeline();
15: }
16:
17: public XElement GetFriendsTimelineByScreenName( string screenName )
18: {
19: return proxy.GetFriendsTimelineByScreenName( screenName );
20: }
21:
22:
23: public XElement Update( string status )
24: {
25: string encodedStatus = AntiXss.HtmlEncode( status );
26: if( encodedStatus.Length > 160 )
27: {
28: throw new ArgumentException( "Status information may not exceed 160 characters" );
29: }
30: return proxy.Update( encodedStatus );
31: }
32:
33: #endregion
34: }
That's it
Now you can use Twitter from your application like I showed in the beginning. For instance to update the users status is as easy as to write
1: TwitterStatusProxy proxy = new TwitterStatusProxy( "username", "password" );
2:
3: XElement result = proxy.Update( "currently testing twitter" );
If you are interested into the interface declarations for the whole Twitter API, send me an email at dparys add microsoft dot com. I will send you the C# project. Why this way, why not sharing? Because I have not tested the complete API declaration. I wrote those API during a train ride with no internet access and had no chance to test. Its up to you. Feedback welcome!