Posting Status Updates To Twitter Via LinqToTwitter: Part 2, Plain-Text Tweets

This is the second in a four-part series on using LinqToTwitter to send status updates (tweets) via the Twitter REST API. Part 1 described creating a Twitter application, which allows you to access the REST API. Part 3 addresses tweeting with media. Part 4 will discuss using the async methods in LinqToTwitter with synchronous methods in your program, such as the Main() function in a console application.

With your Twitter application created, you’re ready to:

  • create the Visual Studio project / solution that will do your tweeting,
  • install the LinqToTwitter Nuget package into that project / solution,
  • authenticate yourself against the Twitter REST API, using the keys you generated in Part 1, and
  • send your first tweet, which can include hashtags, mentions and links — all of which will be properly processed by Twitter.

I’m going to assume you know how to create a Visual Studio solution / project. Since I’m not sure how you intend to tweet — from a website, from a standalone program, as a routine activity you’ve written into a DLL — make whatever kind of project / solution you need to make.

When doing test-driven development like this, I tend to work with console applications when proving models and often, workflows. But you can use any .NET project type that will allow you to run this code, be it Windows Forms or an Azure worker role or even a Silverlight application, of all things.
The LinqToTwitter package in the Visual Studio 2015 Nuget Package Manager.
The LinqToTwitter package in the Visual Studio 2015 Nuget Package Manager.

Add The LinqToTwitter Nuget Package

Once you’ve made your project, you need to add the LinqToTwitter Nuget package to the project.

  • Right-click on your project’s name in Visual Studio’s project explorer panel and select “Manage Nuget packages.”
  • In the dialog box that comes up, make sure you are about to search Online > nuget.org by selecting the online option (nuget.org is automatically added to online searches for Nuget packages).
  • In the search box, type linqtotwitter.
  • You should see the LinqToTwitter package come up. Click the Install button to its right.
  • A number of dependent libraries will be gathered by the Nuget installer, and you will be asked to accept the license terms for all the libraries in question.
  • Click the I Accept button and the Nuget package manager will add those library references to your project.
  • If all went according to plan, the Nuget package manager will indicate that the library has been installed. You can now close the package manager dialog.

Twitter API Authentication Via LinqToTwitter

Authenticating against the Twitter REST API via LinqToTwitter is — and this is a conservative estimate — about 47 billion times easier than attempting to negotiate your own OAuth session via .NET’s built-in web request libraries.

This is especially true when our application needs to only act as a single Twitter user. That is, if we can program our solution so that it only needs to send tweets from one account — and that is the scope of this tutorial / walkthrough — using LinqToTwitter to authenticate is basically as simple as copy and paste of the keys we created in Part 1 of this tutorial.

using LinqToTwitter;

namespace linq2twitter_demo
{
    class Program
    {
        static void Main()
        {
            //we will come back to this in a moment
        }

        static async void SendTweet()
        {
            var auth = new SingleUserAuthorizer
            {
                CredentialStore = new SingleUserInMemoryCredentialStore
                {
                    ConsumerKey = "your consumer KEY from part 1",
                    ConsumerSecret = "your consumer SECRET from part 1",
                    AccessToken = "your access TOKEN from part 1",
                    AccessTokenSecret = "your ACCESS SECRET from part 1"
                }
            };
        }
    }
}

Let’s look at the code above.

On Line 14, we create a SingleUserAuthorizer, which is part of the LinqToTwitter library. This class allows us to store our consumer key, consumer secret, access token and access secret, created in Part 1 of this tutorial, and present them to Twitter for authentication.

The SingleUserInMemoryCredentialStore, on Line 16, is the thing that actually holds our keys. The SingleUserAuthorizer gets our keys when it needs them; otherwise, it holds on to information, returned from Twitter, that lets us know we have successfully authenticated.

I am intentionally being oblique here. Again, OAuth is complicated; not only in how one goes about successfully negotiating authentication, but in terms of how best to preserve that authenticated status — especially in those cases where OAuth expires an authentication after some given period of time.

LinqToTwitter takes care of all of these concerns for us by using the two classes: SingleUserInMemoryCredentialStore, to hold our keys; and SingleUserAuthorizer to negotiate and manage the authentication itself, calling on that key store when it is needed.

TwitterContext Does The Work

These authentication credentials don’t actually do anything for us until we make a request of the Twitter REST API. And to do that, we create a TwitterContext, which takes as its argument the SingleUserAuthorizer we previously created. That is, this TwitterContext will use the account related to the credentials we gave to the SingleUserAuthorizer.

using LinqToTwitter;

namespace linq2twitter_demo
{
    class Program
    {
        static void Main()
        {
            //we will come back to this in a moment
        }

        static async void SendTweet()
        {
            var auth = new SingleUserAuthorizer
            {
                CredentialStore = new SingleUserInMemoryCredentialStore
                {
                    ConsumerKey = "your consumer KEY from part 1",
                    ConsumerSecret = "your consumer SECRET from part 1",
                    AccessToken = "your access TOKEN from part 1",
                    AccessTokenSecret = "your ACCESS SECRET from part 1"
                }
            };

            var context = new TwitterContext(auth);
        }
    }
}

From the MSDN documentation: “A context is an ordered sequence of properties that define an environment for the objects resident inside it. Contexts get created during the activation process for objects that are configured to require certain automatic services, such as synchronization, transactions, just-in-time activation, security, and so on. Multiple objects can live inside a context.”

In other words, you can think of a context as being like a temporary namespace, created to perform a complicated, multi-step task. In this case, because we have a lot of steps involved in making a Twitter REST API request — authenticating, presenting our request, receiving the response and parsing it — the TwitterContext class marshals all the objects used in that process, putting them under a single roof, and abstracting away all the transactional steps we would otherwise need to hand-program repeatedly.

The TwitterContext variable we created on Line 25 contains all the Twitter REST API methods we need to use in order to post a status update (that is, tweet).

And Now, Let’s Tweet

We’re now ready to post our status update, using the TweetAsync method of the TwitterContext object we just created.

TweetAsync takes a single argument: The text we want to tweet. (Actually, you can tweet with location information, including geocoordinates and place IDs. I’m going to just tweet some text.)

Tweeting via the API is just like tweeting via Twitter itself, meaning:

  • Twitter will automatically link up any hashtags we send along. For example, if we include #LinqToTwitter in our tweet, it will be rendered as a hashtag.
  • Additionally, Twitter will also link up any mentions. So, if you include the @dougvdotcom handle in your tweet, it will include a link to my Twitter profile and notify me of the mention.
  • All links will be run through the t.co link shortener.
  • If you link to embeddable media in your tweet, such as a YouTube video or content that has a Twitter card, Twitter will embed that media in your tweet.
  • If your tweet runs longer than the 140 character limit, it will be truncated.

Let’s see the finished code:

using System;
using System.Threading.Tasks;
using LinqToTwitter;

namespace linq2twitter_demo
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine("Program started.");

            try
            {
                Task.Run(() => SendTweet());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Console.WriteLine("Program completed.");
            Console.Read();
        }

        static async void SendTweet()
        {
            var auth = new SingleUserAuthorizer
            {
                CredentialStore = new SingleUserInMemoryCredentialStore
                {
                    ConsumerKey = "your consumer KEY from part 1",
                    ConsumerSecret = "your consumer SECRET from part 1",
                    AccessToken = "your access TOKEN from part 1",
                    AccessTokenSecret = "your ACCESS SECRET from part 1"
                }
            };

            var context = new TwitterContext(auth);

            await context.TweetAsync(
                "Hello World! I am testing @dougvdotcom's #LinqToTwitter demo, at " +
                "https://www.dougv.com/2015/08/posting-status-updates-to-twitter-via-linqtotwitter-part-2-plain-text-tweets"
            );
        }
    }
}
Note that in my Main function, at Line 15 I call Task.Run() with an empty delegate in order to actually send the tweet. I describe this more clearly in Part 4. For now, it’s enough to know that this is one of several ways to run an asynchronous task from a synchronous function.

If all went according to plan, the timeline of the user whose credentials you supplied should now show a tweet:

Handling Errors

Update, 23 October 2015: Hat tip to Greg Lee, who asked for an explanation of error states.

And what if things didn’t go according to plan? The TweetAsync method returns a null Status object if the tweet didn’t go through.

We can tweak our code a bit to handle that:

using System;
using System.Threading.Tasks;
using LinqToTwitter;

namespace linq2twitter_demo
{
	class Program
	{
		static void Main()
		{
			Console.WriteLine("Program started.");

			try
			{
				var result = Task.Run(() => SendTweet());
				result.Wait();
				if(result == null) {
					Console.WriteLine("Tweet failed to process, but API did not report an error");
				}
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
			}

			Console.WriteLine("Program completed.");
			Console.Read();
		}

		static async Task<Status> SendTweet()
		{
			var auth = new SingleUserAuthorizer
			{
				CredentialStore = new SingleUserInMemoryCredentialStore
				{
					ConsumerKey = "your consumer KEY from part 1",
					ConsumerSecret = "your consumer SECRET from part 1",
					AccessToken = "your access TOKEN from part 1",
					AccessTokenSecret = "your ACCESS SECRET from part 1"
				}
			};

			var context = new TwitterContext(auth);

			var status = await context.TweetAsync(
				"Hello World! I am testing @dougvdotcom's #LinqToTwitter demo, at " +
				"https://www.dougv.com/2015/08/posting-status-updates-to-twitter-via-linqtotwitter-part-2-plain-text-tweets"
			);

			return status;
		}
	}
}

Lines 15-19 introduce error trapping for null Status values. We’re going to execute and run our task, assigning it to the value of a variable named result, then wait for its result. If result is null — that is, we got a null Status back from our tweeting function — then we know that for some reason, the tweet didn’t go through, but we didn’t get an error from the Twitter API itself.

To enable the assignment, we change lines 30, 45 and 50 of our tweet-sending function.

This explanation is a little complex. If you are new to async programming, or programming in general, you might want to skip these bullet points, as they involve advanced techniques.
  • Line 30: Rather than using a void function, we need to return something to Main(). In this case, we are returning a Task<Status>. This is explained more clearly in Part 4 of this tutorial; for now, accept that in async programs, most functions return Task<T>, where <T> is an object of some sort.
  • Line 45: We’re not able to simply wait for the tweet to execute; we now need to capture its result, so we can parse it in Main(). So we assign a variable named status to be the Status we get back from Twitter. (Specifically, LinqToTwitter will create a Status object for us after our tweet goes through, which contains information about the tweet, such as its ID number, any hashtags it contains, our profile information, etc.
  • Line 50: We return the Task<Status> as our result of this function. (You can think of a Task as being a kind of wrapper for the underlying object it is handling. In this case, when our function returns a Task<Status>, we can interact with it in our Main function as though it is just a Status object; the Task effectively inherits the properties of its underlying object. I know this is confusing, and I don’t want to belabor it; suffice it to say, when an async method returns a Task<T>, you can effectively interact with it as though it is the underlying object type.)

The catch statement at lines 21-24 will handle errors returned by the Twitter API itself.

In LinqToTwitter, most errors caused by bad REST API responses are handled via a TwitterQueryException. This has the same basic signature as an Exception, but also includes values for specific Twitter REST API error codes, the HTTP Response Code returned by Twitter, and the message returned by the API.

And that’s it for now. In Part 3, I show how to tweet with media (pictures and videos). In Part 4, we’ll look more closely at ways to work with asynchronous methods from a synchronous program method.

This code on github: https://github.com/dougvdotcom/linqtotwitter_demo

I distribute code under the GNU GPL. See Copyright & Attribution for details.

All links in this post on delicious: https://delicious.com/dougvdotcom/posting-status-updates-to-twitter-via-linqtotwitter-part-2-plain-text-tweets

5 Comments

  1. @Dave: Thanks for the feedback. I agree; folks should implement workflows that require and enforce accountability between methods.

    This blog is targeted at beginning coders, most of whom want to get off the ground quickly. I agree with you that this code does nothing to trap errors, and it would be better to return a Task so that errors can be properly trapped. And yes, if you use this code in the raw, you are going to regret it when you encounter errors.

    The goal of this tutorial is to 1. Make the subject fathomable for the beginning coder and 2. get him or her up and running now. Ideally, that includes the graceful handling of errors; but as I mentioned in Part 4:

    We can get objects and primitives back from asynchronous task methods. It is also possible to cancel an async task before it is complete, via a CancellationToken.

    All of this is as complicated as it sounds. So my method was written as a void, so that I could have the best of both worlds: Reduce the code to be as much like synchronous code as I can, while still receiving the benefit of async methods.

    It’s not clean, but it gets the job done.

  2. The TweetAsync method returns a Status object. How can we determine if the Tweet was successful or if it failed what happened?

  3. Thank you for the great article,

    It working perfectly on Xamarin for older version.
    But I found unauthorized exception issue when executing TweetAsync(status, IEnumberable mediaID) if status contains ‘#’ character.

    This issue occurred after update to linqtotwitter v4.2.1 on Xamarin.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  • Check out the Commenting Guidelines before commenting, please!
  • Want to share code? Please put it into a GitHub Gist, CodePen or pastebin and link to that in your comment.
  • Just have a line or two of markup? Wrap them in an appropriate SyntaxHighlighter Evolved shortcode for your programming language, please!