Wednesday, 21 March 2012

Consuming Twitter Feeds in .NET using the Twitter REST API and JSON

My current client had a requirement to provide a twitter feed as part of a SharePoint 2010 intranet site. Unfortunately the RSS feed is no longer an actively supported mechanism for consuming Twitter feeds - instead the recommended way to get Tweets is via the REST APIs. The Twitter widgets were also not an option as I had to cache the results locally to reduce bandwidth consumed by the web part . I tried using LINQ2Twitter - and it worked well until I ran into problems with it not supporting an authenticated HTTP Proxy (ISA Server).

To get around this, I did the following:
  1. Performed a search via using the query syntax e.g. from:news_com_au OR from:time  to get values from time and news_com_au Tweets
  2. Grabbed the querystring to use against the REST API. e.g.!/search/from%3Anews_com_au%20OR%20from%3Atime%20
  3. Grabbed the search string from the above step and did a REST query specifying the JSON result format like so:
  4. With the JSON javascript that was downloaded, I created a JSON serialization class in C# using the great tool JSON2CSHARP - This inferred the information from the JSON results that I provided from Twitter.
The class generated was as follows:
//Twitter JSon Result
namespace CompanyName.HRPortal.Repository.Dto.TwitterJsonResultDto
    public class Metadata
        public string result_type { get; set; }

    public class Result
        public string created_at { get; set; }
        public string from_user { get; set; }
        public int from_user_id { get; set; }
        public string from_user_id_str { get; set; }
        public string from_user_name { get; set; }
        public object geo { get; set; }
        public object id { get; set; }
        public string id_str { get; set; }
        public string iso_language_code { get; set; }
        public Metadata metadata { get; set; }
        public string profile_image_url { get; set; }
        public string profile_image_url_https { get; set; }
        public string source { get; set; }
        public string text { get; set; }
        public object to_user { get; set; }
        public object to_user_id { get; set; }
        public object to_user_id_str { get; set; }
        public object to_user_name { get; set; }

    public class RootObject
        public double completed_in { get; set; }
        public long max_id { get; set; }
        public string max_id_str { get; set; }
        public int page { get; set; }
        public string query { get; set; }
        public string refresh_url { get; set; }
        public List results { get; set; }
        public int results_per_page { get; set; }
        public int since_id { get; set; }
        public string since_id_str { get; set; }

I could then use the standard .NET System.Runtime.Serialization.Json.DataContractJsonSerializer to parse the results and expose it locally as a WCF service (using ASP.NET caching).

Here's the sample code to get the Twitter feed from behind a proxy using REST and JSON:

        public void TestGetPublicTweetsJson()
            string feedUrl =
            HttpWebRequest httpWebRequest = (HttpWebRequest) HttpWebRequest.Create(feedUrl);
            httpWebRequest.Proxy = WebRequest.DefaultWebProxy;

            //Use The Thread's Credentials (Logged-In User's Credentials)
            if (httpWebRequest.Proxy != null)
                httpWebRequest.Proxy.Credentials = CredentialCache.DefaultCredentials;

            using (var httpWebResponse = (HttpWebResponse) httpWebRequest.GetResponse())
                using (var responseStream = httpWebResponse.GetResponseStream())
                    if (responseStream == null) return;
                    DataContractJsonSerializer jsonSerializer =
                        new DataContractJsonSerializer(typeof (RootObject));
                    RootObject root =
                        (RootObject) jsonSerializer.ReadObject(responseStream);

Thats it!