This is the sixth post in my series of thirty-one, titled “31 Days of Silverlight”. You can find the master list here. Today, we are talking about how to talk to the Twitter API from a Silverlight application.
Why Twitter?
Aside from the infinite value that Twitter offers to software developers, there’s another reason we’re doing this. Twitter apps are the new “Hello, World!” apps. No more is it enough to be able to write text to the screen. Now, you need to be able to talk to a web service, and write THAT text to the screen. This tutorial will show you how.
Setting up our Silverlight page
For simplicity, I am going to create a page that has four TextBlocks on it. You could do this many different ways, but I am patterning this off of the way that I created the header on my blog. We will populate those TextBlocks with the most recent posts from my Twitter account. Here’s what the base XAML looks like:
<UserControl x:Class="SilverlightAndTwitterAPI.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="150" />
<RowDefinition Height="150" />
</Grid.RowDefinitions>
<TextBlock x:Name="Tweet1" Width="200" Height="150" Padding="10" Text="Tweet1" />
<TextBlock x:Name="Tweet2" Width="200" Height="150" Padding="10" Grid.Column="1" Text="Tweet2" />
<TextBlock x:Name="Tweet3" Width="200" Height="150" Padding="10" Grid.Row="1" Text="Tweet3" />
<TextBlock x:Name="Tweet4" Width="200" Height="150" Padding="10" Grid.Row="1" Grid.Column="1" Text="Tweet4"/>
</Grid>
</UserControl>
You may also notice a new concept in there: Grid. I wrote a series of articles on the layout options you have available to you in Silverlight, and there you can read about the Canvas, the Grid, and the StackPanel.
Talking To Twitter
Before you think we’re going to be calling the Twitter API directly, I have to take the wind out of your sails. In order to call a web service that lives in another domain, we need to be able to do one of two things:
- Call the Twitter guys and ask them to add a cross-domain policy entry for me.
- Create a proxy web service that can make the calls for me.
You can guess which one will be much easier to implement, so we’re going to go with #2.
Creating some classes.
Right click on your web project, and create two new classes: TwitterUser and TwitterStatus. They’re going to be pretty simple classes, but they’ll be necessary, especially if we want to add to the functionality of this app later.
TwitterUser
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for TwitterUser
/// </summary>
[Serializable]
public class TwitterUser
{
public string Name
{
get;
set;
}
}
TwitterStatus
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for TwitterStatus
/// </summary>
[Serializable]
public class TwitterStatus
{
public string Text
{
get;
set;
}
public TwitterUser User
{
get;
set;
}
}
Creating our web service
I might have to do 31 Days of Web Services at some point in the future, but for today, I’m going to just explain what I’m doing with this web service. We are using a standard ASMX web service, and we’ve got one WebMethod that calls to our Twitter data and returns it as a list. Here’s the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Services;
using System.Xml;
using System.Xml.Linq;
using System.Collections.ObjectModel;
namespace SilverlightAndTwitterAPI.Web
{
/// <summary>
/// Summary description for TwitterProxy
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]
public class TwitterProxy : System.Web.Services.WebService
{
private const string YourUsername = "";
private const string YourPassword = "";
[WebMethod]
public List<TwitterStatus> GetTwitterStatus(string twitterUser)
{
//Create the HTTP path to the Twitter data we want.
string UserTimeline = "http://twitter.com/statuses/user_timeline/" + twitterUser + ".xml";
//Create the HTTP Web Request
WebRequest request = HttpWebRequest.Create(string.Format(UserTimeline, twitterUser));
//Add an empty set of credentials to this Request (we don't need to authenticate for the the request we are making)
request.Credentials = new NetworkCredential(YourUsername, YourPassword);
//Create our response object.
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
XDocument xmlData = XDocument.Load(XmlReader.Create(response.GetResponseStream()));
//Using LINQ, gather the resulting data from our Response object, and populate our list.
List<TwitterStatus> twitterData = (from status in xmlData.Descendants("status")
select new TwitterStatus
{
Text = status.Element("text").Value.Trim(),
User = new TwitterUser()
{
Name = status.Element("user").Element("name").Value.Trim()
}
}).ToList();
//Return our list of data to the calling method.
return twitterData;
}
}
}
That may seem like a few lines of code, but it’s actually pretty simple. We’re just calling to the Twitter API, getting an XML response, and parsing that XML response with LINQ to populate a List of TwitterStatus objects. Now we should probably set our Silverlight app up to call that service.
Calling the service from Silverlight
In our startup method, I make a call to GetTweets(), which is the method that makes our web service call for us. Inside that method, we have three lines of code. The first creates a SoapClient for us, the second creates an event handler on our SoapClient that fires when the asynchronous call has been made, and the third line makes the asynchronous call, passing the specified Twitter username with it.
The event handler method then receives the resulting List of TwitterStatuses, and assigns the Text property of each to each of our four TextBlocks that we created in the beginning. The result? Four populated text blocks with the 4 most recent tweets by the account you specify. Not too hard, right? Here’s the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SilverlightAndTwitterAPI
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
GetTweets("jblankenburg");
}
void GetTweets(string username)
{
TwitterProxyServiceReference.TwitterProxySoapClient twitterClient = new TwitterProxyServiceReference.TwitterProxySoapClient();
twitterClient.GetTwitterStatusCompleted += new EventHandler<SilverlightAndTwitterAPI.TwitterProxyServiceReference.GetTwitterStatusCompletedEventArgs>(twitterClient_GetTwitterStatusCompleted);
twitterClient.GetTwitterStatusAsync(username);
}
void twitterClient_GetTwitterStatusCompleted(object sender, SilverlightAndTwitterAPI.TwitterProxyServiceReference.GetTwitterStatusCompletedEventArgs e)
{
Tweet1.Text = e.Result[0].Text;
Tweet2.Text = e.Result[1].Text;
Tweet3.Text = e.Result[2].Text;
Tweet4.Text = e.Result[3].Text;
}
}
}
Summary
This post was designed to show you how easy it is to call a web service asynchronously from Silverlight. This application is running just below this paragraph, however some RSS readers may exclude it. If you can’t see it, click here to see this Silverlight app calling the Twitter API. You can also download the demo code for this Twitter to Silverlight application here.
Leave a Reply