Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

Twitterlight: A Silverlight Twitter client

Twitter, using simple SMS length messages, has changed how people stay connected.  Here's how to build a Silverlight web client to access the Twitter API and display your tweets in a layout of your choosing.  The Twitterlight code provides a solid starting point for communicating with any RESTful service interface, and you'll also see how to overcome Silverlight's cross-domain call limitations by leveraging a local proxy web service.
Steve's Blog

Difficulty: Intermediate
Time Required: Greater than 10 hours
Cost: Free
Software: Microsoft Visual Studio, Silverlight 2.0 Alpha September Refresh, (NEW) Silverlight 2.0 Beta 1, ComponentOne Sapphire Toolset
Hardware:

Developer Update (5/18/2009)

The Silverlight 2.0 RTW Source Code is available at the link below.  Please note that the RTW version contains no reference to the Sapphire controls used during the SL 2 Beta.

Twitterlight_v22.zip

I am planning to create a new Twitterlight version for Silverlight 3, so I'm sad to say this code base won't be updated past 2.0.  Thanks for the feedback and support!

Developer Update (4/1/2008)

Twitterlight has been updated to the newest Silverlight release: Silverlight 2.0 Beta 1.  You'll need this runtime installed in order to run the app at twitterlight.com.  Don't forget that to compile the code, you must download, install and add references to the appropriate ComponentOne Sapphire control set.

Introduction

I've become a big believer in the power of Twitter to keep an informal social network of like-minded folks loosely yet immediately connected.  Often times developers have a decent number of contacts they'd like to keep in contact with, but perhaps don't always have time to reach out one-on-one often enough.  Twitter provides a mechanism which somehow gives that constantly connected "feel".  As a consultant that works at many sites, I wanted to create a web-based client to allow Twitterers like me to remain connected without the need for installing any applications on their current machine.  Silverlight will give the UI more pop than the existing Twitter site, and provide features like auto-update and TinyURL support.

Notes

If you have a Twitter account, try the app at Twitterlight.com.

The Twitterlight project is written using the Silverlight 2.0 Beta 1.  Previously this article was published using the Silverlight 1.1 Alpha September Refresh.

The Twitterlight project consists of a Silverlight application (TwitterSL), a web site (TwitterSLServer) and a class library containing common controls (TwitterSL.Common). 

By now Silverlight is now infamous for its security setting which prevents cross-domain calls.  What this means is that in order to serve external data, a Silverlight application must call to a web service hosted within the same domain.  This proxy web service can then issue the post to the external data source (here the Twitter API), parse the result, and return back the result to the initial Silverlight code.    Therefore the TwitterSLServer web site contains a local web service (TwitterWebService.asmx) to marshall the Twitter web requests, acting as a the proxy between Silverlight code and the Twitter API.

How it all works

Silverlight application (TwitterSL): The Silverlight project lives and dies with the Page.xaml markup and Page.xaml.cs code-behind.  This code creates the application shell, collects user authentication info, and provides the mechanism for posting new statuses to Twitter (including TinyURL support).  TinyURL, btw, is a must-have for Twitter, because posts are limited to the length of SMS messages, ~140 characters.  TinyURL replaces a full-sized link with a mini-me version of the link, giving you extra room to vent about Roger Clemens or Kanye West's Grammy speech.  Sweet.

The Page.xaml.cs code maintains a reference to the local web service and issues all Twitter API web requests asynchronously to this proxy.  When a response is returned, the XML snippet is parsed and mapped to a new instance of TwitControl, and inserted into the message container.  The app allows users to toggle the type of response returned, from Public (all latest posts), Archive (your posts), Replies (directed at you), and the standard Friends (you and all your buddies).

Control Toolset (ComponentOne Sapphire): I used ComponentOne's new Sapphire control toolset for this project.  These controls add some nice functionality to a Silverlight project without forcing developers to create everything from scratch.  I used C1's Label, LinkLabel and StackPanel to create the TwitControl, and the StackPanel and FlowPanel within Page.xaml to setup the layout of the application.  I recommend trying these controls if you're starting out in Silverlight: a trial version is provided, and the support response was solid when I ran into a few minor issues.  I'm excited to see the improvements to both Silverlight and the available control toolsets as they evolve together.  One thing to note is that I created all third-party controls at runtime in order to avoid some VS designer issues, which should be corrected in the future. 

You'll need to download and install this toolset from the ComponentOne site, and add references to C1.Silverlight.dll in order to compile the project.

Here's how to add a few controls to the XAML (the sp.ReplacePlaceHolder call swaps out a Silverlight placeholder with the newly created StackPanel):

C#:
/// <summary>
/// Builds third party controls dynamically at runtime
/// </summary>
private void CreateComponentOneControls()
{
    TextBlock twitMessage = new TextBlock();
    twitMessage.Width = 290;
    twitMessage.FontSize = 11;
    twitMessage.Foreground = new SolidColorBrush(Colors.White);
    twitMessage.TextWrapping = TextWrapping.Wrap;
    _twitMessage = twitMessage;
            
    ... other controls initialized...
    twitTextPlaceholder = implementationRoot.FindName("twitStackPanelPlaceholder") as Canvas;
                        
    C1StackPanel sp = new C1StackPanel();
    sp.IsHorizontal = false;
    sp.ReplacePlaceHolder(twitTextPlaceholder, true);
    sp.AutoSize = AutoSize.Both;
    sp.Padding = new Thickness(5, 5, 2, 5);
    sp.HorizontalAlignment = Alignment.Near;
    sp.VerticalAlignment = Alignment.Near;
    sp.ChildSpacing = new Size(2, 0);
                       
    sp.Children.Add(twitMessage);        
}
VB:
''' <summary>
''' Builds third party controls dynamically at runtime
''' </summary>
Private Sub CreateComponentOneControls()
    Dim twitMessage As New TextBlock()
    twitMessage.Width = 290
    twitMessage.FontSize = 11
    twitMessage.Foreground = New SolidColorBrush(Colors.White)
    twitMessage.TextWrapping = TextWrapping.Wrap
    _twitMessage = twitMessage

    ...other controls initialized ...
    twitTextPlaceholder = CType(implementationRoot.FindName("twitStackPanelPlaceholder"), Canvas)

    Dim sp As New C1StackPanel()
    sp.IsHorizontal = False
    sp.ReplacePlaceHolder(twitTextPlaceholder, True)
    sp.AutoSize = AutoSize.Both
    sp.Padding = New Thickness(5, 5, 2, 5)
    sp.HorizontalAlignment = Alignment.Near
    sp.VerticalAlignment = Alignment.Near
    sp.ChildSpacing = New Size(2, 0)

    sp.Children.Add(twitMessage)
End Sub  

Control library (TwitterSL.Common): The custom control library contains just one object: TwitControl.  An instance of this control is dynamically created for each Tweet returned from Twitter.   The control is then inserted at runtime into the parent Tweet container.  Take a look at the XAML of this control to see how some simple animation storyboards can be tied to each control and wired up to individual control events.

Web project (TwitterSLServer): The web site project contains a single web page which hosts the Silverlight container.  The project has been linked to the Silverlight project, and the default.htm and Page.xaml objects have been copied to the site.  The web project is set as the startup project, but remember all of the "work" is done within the TwitterSL Silverlight project.

Proxy web service (TwitterWebService.asmx):  The local TwitterWebService .asmx is part of the TwitterSLServer web project.  This is the proxy service used to contact the Twitter API directly.  The web service allows for async behavior by providing each public method with a BeginXXX() and EndXXX() variant.  The Silverlight project can call BeginXXX() and continue processing; the EndXXX() is invoked once the request is completed by Twitter and the proxy web service.

Twitter API: Twitter provides a Representational State Transfer (RESTful) service to allow third-party applications to access the Twitter message exchanges.  The API calls utilize HTTP Basic Authentication delivered via HTTP Requests to specified URLs, and returns back a list of messages in the desired format (XML, JSON, etc).  The proxy web service delivers an XML snippet back to the Silverlight calling code for parsing and display.  You can see how a request is created in the proxy web service methods below:

C#:

[WebMethod]
public string GetArchive(string username, string password)
{
    try
    {
        return GetRequest(string.Format(@"http://twitter.com/statuses/user_timeline/{0}.xml", username), username, password);
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

private string GetRequest(string uri, string username, string password)
{
    WebRequest request = HttpWebRequest.Create(uri);

    if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
    {
        request.Credentials = new NetworkCredential(username, password);
    }

    WebResponse res = request.GetResponse();
    StreamReader stream = new StreamReader(res.GetResponseStream());
    string data = stream.ReadToEnd();
    stream.Close();
    return data;
}

VB:

<WebMethod()> _
Public Function GetArchive(ByVal username As String, ByVal password As String) As String
    Try
        Return GetRequest(String.Format("http://twitter.com/statuses/user_timeline/{0}.xml", username), username, password)
    Catch ex As Exception
        Throw ex
    End Try
End Function
Private Function GetRequest(ByVal uri As String, ByVal username As String, ByVal password As String) As String
    Dim request As WebRequest = HttpWebRequest.Create(uri)

    If Not String.IsNullOrEmpty(username) AndAlso Not String.IsNullOrEmpty(password) Then
        request.Credentials = New NetworkCredential(username, password)
    End If

    Dim res As WebResponse = request.GetResponse()
    Dim stream As StreamReader = New StreamReader(res.GetResponseStream())
    Dim data As String = stream.ReadToEnd()
    stream.Close()
    Return data
End Function

Putting it together

In the TwitterSL.Page class, the action kicks off when the user enters a Twitter username/password, and presses the "Get" button.  The dropdown beside it determines which web request type will be issued.  An AutoRefresh toggles, of course, the auto refreshing of the current message list.  The line under "AutoRefresh" fades until the refresh occurs, one of the simple animations added to the XAML.

The Get button's click event trickles down to the GetWebRequest method, which calls the appropriate proxy web service method.  Notice the call here using the "Begin" prefix, and passing a new AsyncCallback object to invoke the service asynchronously.  The callback object specifies GetWebRequestResult as the target when the call finishes.

C#:

_twitterWebService.BeginGetTwits(username, password, new AsyncCallback(GetWebRequestResult), null);

VB:

_twitterWebService.BeginGetTwits(username, password, New AsyncCallback(AddressOf GetWebRequestResult), Nothing)

The web service simply sets up the appropriate url, builds an HTTP web request with authentication (if required), and issues the call (nothing too shocking here, but take a look at the code if you're not familiar with building up a web request).

Once the web service work is done, we're asynchronously delivered to the previously mentioned GetWebRequestResult method.  This drops us into LoadTwits, which does the dirty work of parsing the returned XML snippet, creating new instances of the TwitControl for each message element and adding them to the parent container.

It's here, however, where the simplistic beauty of RESTful interfaces show their harsh side: we're pretty dependent on their format, and this parsing code could easily break.  Also, of course, the REST won't give us strong typing.  Hey, this would be a good place for a wrapper project, a la the Facebook Developer Toolkit.  And speaking of enhancements....

Challenges to you

The fun & frustration of coding with new technology is overcoming the limitations of a limited feature set.  The Twitterlight project is ripe for feature development in the coming months, as the Silverlight 2.0 Beta releases and control toolsets continue to emerge.  Some challenges include:

  • The TwitControl needs rich text support, to parse any urls into into clickable hyperlinks.  Currently links show below the message as "Follow Link"
  • Add more user credential security vs. current Basic Authentication
  • Incorporate new toolset and SIlverlight features as released

Bio

Steve Holstad is a software development consultant for Clarity Consulting, based in Chicago, IL. Check out his blog for other writings and contact information.

Follow the Discussion

  • SamSam

    Thanks for the help but its still not working (Twitterlight). I'm just redirected to a telling me that the page I wanted requires Silverlight.

    I asked other ppl to check it and all had the same problem (although in fairness I think all of them hadn't yet installed Silverlight so they would have all been fresh installs).

  • Clint RutkasClint I'm a "developer"

    @Sam:  Try the 2.0 beta.  Hopefully that will fix it.  If not, contact me with the link at the top and we'll figure out how to get you up and running then post it back here so everyone can get it to work.

  • David OvertonDavid Overton

    I have the same problem as Sam - I have IE8 and the 2.0 beta released after MIX08 and I get told I need Silverlight.  I have other 2.0 sites that are fine.

    Happy to help diagnose if required.

  • Clint RutkasClint I'm a "developer"

    @Sam and @David Overton:

    I got in contact with Steve and some Silverlight 1.1 calls were foobar'ed in 2.0 beta.  The app I wrote had the same issue and I just updated it yestarday.  Steve is going to update this when he gets the chance.

    1.1 was cool but since it was Alpha, stuff like this was bound to happen.

  • Steve HolstadSteve Holstad

    Hey all, thanks for checking out the article.  I've updated http://www.twitterlight.com to use the Silverlight 2.0 Beta 1, and the installation prompt is (finally) pointing to the correct version.  

    The latest code (C#) is posted above as well.

    my apologies for the confusion... aren't alphas fun!!  -steve

  • the bright lightsthe bright lights

    Ok ok, I&#39;ve bitten the bullet and upgraded the Twitterlight Silverlight Twitter client to Silverlight

  • Steve HolstadSteve Holstad

    One more update: I heard that some Mac+FireFox users were having trouble typing in the ComponentOne Textboxes.  I've updated the app to use the new Silverlight Beta textboxes.  I don't have a Mac to test on, so feedback is appreciated.

  • BenitonBeniton

    Nice work

    But the password field seems to be a normal field

  • Steve HolstadSteve Holstad

    yeah, I had to drop the sapphire password txt control because they didn't work on Apple+Firefox systems.  Didn't see this functionality in the Silverlight controls.

    plus, this is more C4Fun than production app. <g>

  • SamSam

    Thanks Steve. It works now. I'll have a crack at the project now I can see what it should look like.

  • ViralViral

    No reference detected C1.Silverlight.dll

    So i want to download that file..??

    From where can i get that file..???

  • Mark SchmidtMark Schmidt

    Lots of errors with the C1 library now. C1Label isn't even in there anymore. Too many to go and fix for me.

  • Steve HolstadSteve Holstad

    The posted (original) source is using the defunct SL Beta 2.  You can download the SL 2 RTW release code at:

    http://employees.claritycon.com/sholstad/publicsource/Twitterlight_v22.zip

    I'll update the article links asap.  Thanks all.

    Steve

  • Clint RutkasClint I'm a "developer"

    @Mark and @Viral looking into this

  • Clint RutkasClint I'm a "developer"

    Thanks for bringing this to our attention!  We've fixed it.  We were pointing to SL2 Beta files.  Sorry about that

  • CrystalCrystal

    Pretty damn cool! I like it a lot. I'm using it right now! Anyway to change the background color?

  • Clint RutkasClint I'm a "developer"

    @Crystal, we have the source provided so you can go into the XAML and alter it to whatever you want!

  • srisakthisrisakthi

    hi, this widget is very nice and very useful for me,bcoz now i'm trying to develop a widget like this..

    Thanks....

  • AmitAmit

    Hi, nice app, I want to show latest update from each user I am following , Is it possible

  • RTW PhoenixRTW Phoenix

    When will the SL3 version be out?

    Thank you

  • Clint RutkasClint I'm a "developer"

    @RTW Phoenix, sobees has a pretty neat silverlight twitter app, http://www.sobees.com/

  • steve holstadsteve holstad

    Hey all, thanks for the comments.  twitterlight has morphed into Gadfly, please have a look:  

    http://gadfly.claritycon.com

    -steve

Remove this comment

Remove this thread

close

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.