Background
Initially when I started with Silverlight learning series, I had mentioned that I’ll create a sample app similar to TweetDeck. In this post I intend to start with a very simple application which attempts to ultimately wind up similar to TweetDeck. I start off with connecting to Twitter using a Silverlight 4 application. I’ll probably add Facebook to it as well later, once Twitter client is stable. This is the first post which shows how to connect to Twitter using a managed C# API called TweetSharp.
TweetSharp API
We can develop client applications for Twitter using the Twitter API. Twitter offers different mechanisms to connect using OAuth, xAuth etc. In this post I’ll be consuming the public feed of Twitter and as such will not use any for of Authentication. In the later post I’ll be using the dedicated user to connect to Twitter and we’ll see how to use different Authentication methods.
Instead of building everything from scratch I decided to use an open source API for C# which is called TweetSharp. You can find out more about the TweetSharp here. There is a NuGet package available as well using which you can add the dll to your project. So I made use of it to add reference to the required dll and its dependencies to the project. Lets see how can we make use of this API to connect to Twitter.
Connect to Twitter using TweetSharp
I created a new Silverlight 4 application and named it NGTweet. You can say its an acronym for Next Generation Tweet or Nilesh Gule’s Tweets . From this Silverlight application we’ll have to make calls to the Twitter API using TweetSharp. But since Silverlight is a client side technology, we cannot directly make call to Twitter from the Silverlight application.
So I added a WCF service to the solution which will be the mediator between the Silverlight application and Twitter. I named the service project as TweetSharpService. For the time being we’ll have just a single method in the service to fetch the public timeline from Twitter.
[ServiceContract]
public interface ITweetSharpService
{
[OperationContract]
GetDataResponse GetTweetsOnPublicTimeline();
}
I like to encapsulate the request and response of the service using the Request-Response Pattern. Since this method is not taking any input parameter I have avoided creating the request object. But there is a GetDataResponse object which will contain the response from the service method. Lets look at the structure of the response object in little bit more detail.
[DataContract]
public class GetDataResponse
{
[DataMember]
public IEnumerable<NGTweeterStatus> TweeterStatuses { get; set; }
}
There is only one property called TwitterStatuses which is a collection of NGTweeterStatus. I’ll explain in a short while the need for this NGTweeterStatus class. Lets look at the details of NGTweeterStatus.
[DataContract]
public class NGTweeterStatus
{
[DataMember]
public string ScreenName { get; set; }
[DataMember]
public string Tweet { get; set; }
}
As of now there are only two members for this class, ScreenName and Tweet. Both the members are marked with the DataMember attribute and the class as a whole is marked with the DataContract attribute.
After these basic classes are in place lets look at the service implementation.
public class NgTweetSharpService : ITweetSharpService
{
public GetDataResponse GetTweetsOnPublicTimeline()
{
TwitterService service = new TwitterService();
IEnumerable<TwitterStatus> tweets = service.ListTweetsOnPublicTimeline();
TweeterStatusAdapter adapter = new TweeterStatusAdapter();
return new GetDataResponse { TweeterStatuses = adapter.Convert(tweets) };
}
}
As we can see this is the place where the TwitterService is coming into the picture. This is the place from where we instantiate the TweetSharp API’s TwitterService class. We get the list of tweets on the public time line. There is a minor problem here. Some of the properties of TwitterStatus class defined within the TweetSharp API are only getters or only setters. Because we are using WCF service, the objects are serialized. And for the objects to be serialized we need to have the properties as read write properties. Hence I created the wrapper called NGTweeterStatus.
Finally, there is an adapter also coming into the picture called TweeterStatusAdapter. This is a two way adapter which will convert the TweeterStatus from TweetSharp API to NGTweeterStatus and vice versa. At the moment I have implemented only the method which converts TwitterStatus to NGTweeterStatus. Here is an implementation of the adapter.
public class TweeterStatusAdapter
{
public IEnumerable<NGTweeterStatus> Convert(IEnumerable<TwitterStatus> tweets)
{
return tweets.Select(twitterStatuse => new NGTweeterStatus { ScreenName = twitterStatuse.User.ScreenName, Tweet = twitterStatuse.Text }).ToList();
}
}
Its a very simple implementation of the Adapter pattern which adapts the properties of one object to another. People who are well versed with Domain Driven Design can make use of the Mapper pattern. In future we can also look the possibility of using AutoMapper. For time being in the context of this demo whatever we have would suffice.
Add clientaccess.xml and crossdomain.xml files
If we want to make calls to services outside the domain of the server where the Silverlight application is hosted, we need to add the crossdomain.xml file to the root of the project. And also the clientaccess.xml file. You can read more about these two files on MSDN. At this point you can build the service project and browse the service. You should get the page similar to the one shown below
Add Service reference to Silverlight project
Once the service is up and running we can add the service reference to the Silverlight application and make call to the service method. I added the reference with name NGTweetSharpService. In the MainPage I am going to use a ListBox to display the ScreenName and Tweet from the public timeline. I modified the ListBox control’s item template and data template to display the data in two TextBlock controls as shown below
<StackPanel ScrollViewer.VerticalScrollBarVisibility="Auto" Height="500">
<ListBox Name="lstTweets" Width="400">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Background="BlanchedAlmond" Margin="3" HorizontalAlignment="Stretch">
<StackPanel>
<TextBlock Text="{Binding ScreenName, Mode=TwoWay}"/>
<TextBlock Text="{Binding Tweet, Mode=TwoWay}"/>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
And the last thing to do is to call the service and set ItemsSource of the listbox as the collection returned from the service.
public MainPage()
{
InitializeComponent();
Loaded += MainPage_Loaded;
}
private void MainPage_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
TweetSharpServiceClient client = new TweetSharpServiceClient();
client.GetTweetsOnPublicTimelineCompleted += client_GetTweetsOnPublicTimelineCompleted;
client.GetTweetsOnPublicTimelineAsync();
}
private void client_GetTweetsOnPublicTimelineCompleted(object sender, GetTweetsOnPublicTimelineCompletedEventArgs e)
{
GetDataResponse response = e.Result;
lstTweets.ItemsSource = response.TweeterStatuses;
}
The code above is self explanatory. We create a client to the service and call the async method by setting the callback. In the callback we assign the value returned from the service call to the ItemsSource property of the listbox control. If everything goes fine, you should see a screen similar to the one shown below.
Conclusion
As demonstrated in this example, it is very easy to use the TweetSharp API to connect to Twitter using a Silverlight client application. In the future posts we’ll see how to refine this application. We used a very simple in this post to connect to the public time line of Twitter. As the series goes on we’ll see how to filter tweets based on authenticated user. I hope this was a good starting point.
Note: I have uploaded all the contents of the TweetSharp and its dependent dlls. This has increased the size of the uploaded code by huge margin. Will try to upload only the required files next time.
As usual the source code is available for download at Dropbox.
Until next time Happy Programming
great article,keep up the good work!
ReplyDelete