Integrating Twitter in Windows Store Apps with “Linq to Twitter” – Boredom Challenge Day 28

Standard

In this previous blog post I’ve talked about why integrating Twitter in our apps is a good idea and then created a sample app which fetched a public Twitter feed without requiring the user to log in. However, this was just a small feature, and we may wish to take it a step further and allow the user to login to Twitter and publish tweets directly from our app, or maybe make the user follow a specific Twitter user, display favorite tweets or allow the user retweet and so on.

1

If you try to use Twitter’s REST API to do this, however, you are in for quite a ride. Because of security reasons, trying to do some operations may cause you to mutter “wtf” to yourself several times in a short time span, such as constructing the HTTP request for authorization, since it only accepts parameters that require specific encryptions and encodings (see for yourself). It is, of course, not impossible, but it is time consuming. Therefore, we’ll be going the easy way, by using an open source 3rd party library called Linq to Twitter that does these operations itself and allows us to reach every function of the Twitter API way more easily. Linq to Twitter also allows us to query Twitter using Linq syntax (hence the name), which I really liked.

So, in this article we’ll create a Windows Store app that allows the user to sign in with his/her Twitter account, get and display the user’s basic information, and let the user send a tweet from inside the app.

Before going on to create the Windows Store App, make sure you created an app on http://dev.twitter.com which has Read and Write access. Also make sure you set the Callback URI (even if we’re not going to use it for anything), because otherwise you’ll get a “401: Unauthorized” error. You can check the beginning of the previous blog post for step by step instructions (just don’t forget setting the access and callback URI).

2

Ok then, we’ll create a blank Windows Store app project in Visual Studio.

3

We will add Linq to Twitter to our project by right-clicking References in Solution Explorer, selecting Manage Nuget Packages, and searching for “linqtotwitter”.

Important Warning: Linq to Twitter has been updated after this article was written and there have been some changes to the WinRTAuthorizer class. Because of these changes, the source code provided in this article will not work with the latest version of Linq to Twitter. You could consult Linq to Twitter’s documentation to learn how to use it, or you could go to the package manager console and enter ‘Install-Package linqtotwitter -Version 2.1.10′ command to download the version used in this article. Many thanks to Tayyeba Riaz for pointing this out. 🙂

4

Next, in our interface, we’ll have the following items: Buttons for signing in/out and sending the tweet, a TextBox to enter the tweet content, Images to show the user’s profile picture and background image and TextBlocks to display the user’s information.

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Image x:Name="ImageUserBackground" Stretch="UniformToFill" Opacity="0.3"/>
        <Image x:Name="ImageUser" HorizontalAlignment="Left" Height="100" Margin="718,173,0,0" VerticalAlignment="Top" Width="100" Stretch="UniformToFill"/>
        <Button x:Name="ButtonSignInOut" Content="Sign In" HorizontalAlignment="Left" Margin="100,100,0,0" VerticalAlignment="Top" Click="ButtonSignInOut_Click"/>
        <TextBox x:Name="TextBoxTweet" HorizontalAlignment="Left" Margin="105,173,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="130" Width="370" Visibility="Collapsed"/>
        <Button x:Name="ButtonSendTweet" Content="Send Tweet" HorizontalAlignment="Left" Margin="105,308,0,0" VerticalAlignment="Top" Click="ButtonSendTweet_Click" Visibility="Collapsed"/>
        <ProgressBar x:Name="ProgressBar" Height="10" Margin="0" VerticalAlignment="Top" Visibility="Collapsed"/>
        <TextBlock x:Name="TextBlockName" HorizontalAlignment="Left" Margin="514,289,0,0" VerticalAlignment="Top" FontSize="15" FontFamily="Segoe UI Light" Width="500" FontWeight="Light" TextAlignment="Center"/>
        <TextBlock x:Name="TextBlockScreenName" HorizontalAlignment="Left" Margin="514,313,0,0" VerticalAlignment="Top" FontSize="15" FontFamily="Segoe UI Light" Width="500" FontWeight="Light" TextAlignment="Center"/>
        <TextBlock x:Name="TextBlockDescription" HorizontalAlignment="Left" Margin="514,338,0,0" VerticalAlignment="Top" FontSize="15" FontFamily="Segoe UI Light" Width="500" FontWeight="Light" TextWrapping="Wrap" TextAlignment="Center"/>
    </Grid>

Then, we’ll add the necessary code to the MainPage.xaml.cs file. I’m going to paste it completely first, then explain the what and why of it step by step (Don’t forget to put your own consumer key and consumer secret).

using LinqToTwitter;
using Windows.Storage;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Popups;
        WinRtAuthorizer authorizer = new WinRtAuthorizer();
        TwitterContext twitterContext;

        string consumerKey = ""; //put your consumer key here
        string consumerSecret = ""; //put your consumer secret here

        public MainPage()
        {
            this.InitializeComponent();
            this.Loaded += MainPage_Loaded;
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            authorizer.Credentials = new LocalSettingsCredentials()
            {
                ConsumerKey = consumerKey,
                ConsumerSecret = consumerSecret
            };
            authorizer.UseCompression = true;
            authorizer.Callback = new Uri("http://eren.ws");
            if (authorizer.IsAuthorized == true)
            {
                twitterContext = new TwitterContext(authorizer);
                ButtonSignInOut.Content = "Sign Out";
                ButtonSendTweet.Visibility = Visibility.Visible;
                TextBoxTweet.Visibility = Visibility.Visible;
                GetUserInfo();
            }
        }

        async private void ButtonSignInOut_Click(object sender, RoutedEventArgs e)
        {
            if (authorizer.IsAuthorized == false)
            {
                ProgressBar.IsIndeterminate = true;
                ProgressBar.Visibility = Visibility.Visible;

                await authorizer.AuthorizeAsync();

                ProgressBar.Visibility = Visibility.Collapsed;
                ProgressBar.IsIndeterminate = false;

                if (authorizer.IsAuthorized == true)
                {
                    twitterContext = new TwitterContext(authorizer);
                    ButtonSendTweet.Visibility = Visibility.Visible;
                    TextBoxTweet.Visibility = Visibility.Visible;
                    ButtonSignInOut.Content = "Sign Out";
                    GetUserInfo();
                }
                else
                {
                    //User cancelled operation
                }
            }
            else
            {
                ProgressBar.IsIndeterminate = true;
                ProgressBar.Visibility = Visibility.Visible;

                ApplicationData.Current.LocalSettings.DeleteContainer("TWStore");
                authorizer.Credentials = new LocalSettingsCredentials()
                {
                    ConsumerKey = consumerKey,
                    ConsumerSecret = consumerSecret
                };

                ImageUserBackground.Source = null;
                ImageUser.Source = null;
                TextBlockName.Text = String.Empty;
                TextBlockScreenName.Text = String.Empty;
                TextBlockDescription.Text = String.Empty;
                ButtonSendTweet.Visibility = Visibility.Collapsed;
                TextBoxTweet.Visibility = Visibility.Collapsed;

                ProgressBar.Visibility = Visibility.Collapsed;
                ProgressBar.IsIndeterminate = false;

                ButtonSignInOut.Content = "Sign In";
            }
        }

        async private void GetUserInfo()
        {
            User currentUser = (from user in twitterContext.User
                                where user.Type == UserType.Show && user.ScreenName == authorizer.Credentials.ScreenName
                                select user).ToList<User>().SingleOrDefault();

            if (currentUser != null)
            {
                ImageUserBackground.Source = new BitmapImage(new Uri(currentUser.ProfileBackgroundImageUrl));
                ImageUser.Source = new BitmapImage(new Uri(currentUser.ProfileImageUrl.Replace("normal", "bigger")));
                TextBlockName.Text = currentUser.Name;
                TextBlockScreenName.Text = String.Format("@{0}", currentUser.ScreenName);
                TextBlockDescription.Text = currentUser.Description;
            }
            else
            {
                MessageDialog messageDialog = new MessageDialog("Could not get user information.");
                await messageDialog.ShowAsync();
            }
        }

        async private void ButtonSendTweet_Click(object sender, RoutedEventArgs e)
        {
            if (TextBoxTweet.Text.Length > 140)
            {
                MessageDialog messageDialog = new MessageDialog("Your tweet can not be longer than 140 characters.");
                await messageDialog.ShowAsync();
            }
            else
            {
                Status tweet = twitterContext.UpdateStatus(TextBoxTweet.Text);

                if (tweet != null)
                {
                    MessageDialog messageDialog = new MessageDialog("Tweet sent.");
                    await messageDialog.ShowAsync();
                }
                else
                {
                    MessageDialog messageDialog = new MessageDialog("Could not send tweet.");
                    await messageDialog.ShowAsync();
                }
            }
        }

Ok, let’s see what we’re doing.

The WinRTAuthorizer class (authorizer variable) is where we add the consumer key and consumer secret values. This variable is the one that creates the interface for the user to sign in, and if the user signs in successfully, it also contains the OAuthToken and access token, allowing us to take actions on behalf of the user. When these 4 values are complete, then the IsAuthorized property of the authorizer will be true, so we can check it to see if the user is signed in.

However, something you should be careful about is how it stores the credentials. In this example we used it to keep them in the LocalSettings of the app. You can also select to keep it in LocalData (as a file), or RoamingSettings – RoamingData to allow the user to sign in once and never sign in again from another computer. However, keeping it as a file has some issues when signing out, so I’d recommend keeping it in the app settings.

Continuing on. In MainPage_Loaded, we filled the credentials in authorizer, and checked if a user is already signed in (it automatically gets the signed in user’s tokens from app settings this way).

In ButtonSingInOut_Click, if we aren’t signed in, we sign in using the authorizer and then give that authorizer to TwitterContext object, which is the object we’ll use for our actions on Twitter. If we are already signed in, then we sign out by deleting the related container in the LocalSettings so our user’s credentials will be deleted (and create an empty one afterwards to reset the authorizer).

In GetUserInfo, as you can see we use Linq syntax to get our user’s information from Twitter.

And finally in ButtonSendTweet_Click, we check the length of our Tweet and send it if it is shorter than 140 characters.

Now run the app and sign in using your Twitter account and try to send a tweet from the app. Note that it may take a while for your background image to be shown because they can have large sizes.

5

6

That’s it. 🙂 If you wish to do more things (retweeting, following people, sending tweets with pictures or videos) you can take a look at the documentation of Linq to Twitter on how you can accomplish them.

By the way, I couldn’t find how to get the header (banner) image of a user. I think it is not supported by Twitter.

You can get the source code of the app here.

Thank you for reading. 🙂

9 thoughts on “Integrating Twitter in Windows Store Apps with “Linq to Twitter” – Boredom Challenge Day 28

  1. Juan Camilo

    The consumer key and consumer secret are the user name and password from user twitter account?. If it is. Where we use the twitter developer site register information?, If not When we put the specific user info in order to get his information?

    • No, the consumer key and consumer secret are not the username and password of the user’s account. They are the twitter developer site registration information, as you can see in the picture below:

      About the user account information, I’ll go over the example code which follows like this: We have a WinRTAuthorizer object that allows a user to log in with his/her twitter account (in ButtonSignInOut_Click). We do not have control over this process; we just know if the login is successful or not. If the user signs in successfully, the authorizer object tells us this and contains the user’s id and screen name. In the example, we get the screen name of the user through the authorizer, and then get the complete user information via that screen name (in GetUserInfo). Later, when we want to do operations on behalf of the user, we use the TwitterContext object (we create this object with the authorizer so it already knows the user’s id and screen name, in ButtonSignInOut_Click). Keep in mind that we can never access a user’s password.

      Finally, the authorizer object automatically stores this user id and screen name information in WinRT app’s application settings, so when the user closes and reopens the app he/she won’t need to login again. That is why we are deleting the “TWStore” app setting folder when the user is signing out in ButtonSignInOut_Click.

  2. Very helpful tutorial. Thanks for this 🙂
    Just to point out Linqtotwitter has been updated due to which there are certain errors eg implementation of the WinRtAuthorize class which is different in the next version. To solve that and follow this tutorial exactly, we can install this version of linqtotwitter by going to package manager console and typing in ‘Install-Package linqtotwitter -Version 2.1.10’ which installs ‘linqtotwitterRT’ and it works perfectly fine then 🙂

Comment