Using Twitter API v1.1 with .net (oAuth) – no 3rd party libraries


Due March 2013 Twitter API V1.0 get deprecated and all requested to use V 1.1 instead. I had a Twitter web part created for a public facing site and I had to update it to this new API version. Most of the articles i read including Twitter it says its pretty straight forward. But I had to go through a very hard time figuring out how to connect to API using oAuth 1.0 and how to pass additional parameters. There are misty hidden behind the API calls and signing signatures that not described in detail in any documentation.This attempt is to clarify the procedure as much as possible and give you a working version of a implementation.
Code sample given below is generalized and you can pass any twitter parameter related to user time line related query. Just add the parameters to additional_parameters section.

If you had already started trying to implement this you may have received some common error message while testing it.

The remote server returned an error: (400) Bad Request.

The remote server returned an error: (401) Unauthorized.

Some Key reasons to get those error messages is not relevant directly to the error message it self.

1) Base string used to create signature should have there parameters alphabetically sorted. (thank you Priyantha Sampath Lankapura for pointing this out to me Smile )

2) What ever the parameters included in the signature must present in the request url sent to twitter. You cannot change a single parameter value. Authenticity of the request is validated through the URL and the signature sent in the header.

(The complete list of error messages can be found here.

https://dev.twitter.com/docs/error-codes-responses)

Please note all the tokens provided below are incorrect and you need to replace them with your own application tokens you created to get this sample work. If you don’t have these token already created you can do so from twitter developer site.

https://dev.twitter.com/docs/auth/tokens-devtwittercom

 

Code Sample
  1.          
  2.          try
  3.             {
  4.                 CultureInfo _culture = new CultureInfo(“en-US”);
  5.                 #region oAuth realted parameters
  6.                 var oauth_token = “176122-SQA1amiFz1Q1cX7ZRRzyJsbyWfnwb5zQtOsZY”;
  7.                 var oauth_token_secret = “2ZhjEPv4bP5ojpj6hPSLFEmW2nAsYzIrEkhL5YJs”;
  8.                 var oauth_consumer_key = “2rYXfK6o76tz2uwIUJ9A”;
  9.                 var oauth_consumer_secret = “38TDM2qD1Fi5M51yFxljAC9dX5TQD1uusAyUEVw”;
  10.                 var resource_url = https://api.twitter.com/1.1/statuses/user_timeline.json”;
  11.                 var oauth_version = “1.0”;
  12.                 var oauth_signature_method = “HMAC-SHA1”;
  13.                 var oauth_nonce = Convert.ToBase64String(new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture)));
  14.                 var timeSpan = DateTime.UtcNow – new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
  15.                 var oauth_timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString(CultureInfo.InvariantCulture);
  16.                 SortedDictionary<string, string> oauth_parameters = new SortedDictionary<string, string>();
  17.                 oauth_parameters.Add(“oauth_consumer_key”, oauth_consumer_key);
  18.                 oauth_parameters.Add(“oauth_nonce”, oauth_nonce);
  19.                 oauth_parameters.Add(“oauth_signature_method”, oauth_signature_method);
  20.                 oauth_parameters.Add(“oauth_timestamp”, oauth_timestamp);
  21.                 oauth_parameters.Add(“oauth_token”, oauth_token);
  22.                 oauth_parameters.Add(“oauth_version”, oauth_version);
  23.                 #endregion oAuth realted parameters
  24.                 #region Twitter time line related additonal parameters
  25.                 // Some variable parameters
  26.                 var screen_name = “twitterapi”;
  27.                 int count = 5;
  28.                 SortedDictionary<string, string> additional_parameters = new SortedDictionary<string, string>();
  29.                 additional_parameters.Add(“screen_name”, Uri.EscapeDataString(screen_name));
  30.                 additional_parameters.Add(“count”, count.ToString());
  31.                 additional_parameters.Add(“exclude_replies”, “false”);
  32.                 additional_parameters.Add(“include_rts”, “true”);
  33.                 additional_parameters.Add(“trim_user”, “true”);
  34.                 additional_parameters.Add(“contributor_details”, “true”);
  35.                 #endregion Twitter time line related additonal parameters
  36.                 #region Merge all parameters together and sort them
  37.                 SortedDictionary<string, string> mergerd_parameters = new SortedDictionary<string, string>();
  38.                 foreach (var item in oauth_parameters)
  39.                 {
  40.                     mergerd_parameters.Add(item.Key, item.Value);
  41.                 }
  42.                 foreach (var item in additional_parameters)
  43.                 {
  44.                     mergerd_parameters.Add(item.Key, item.Value);
  45.                 }
  46.                 #endregion Merge all parameters together and sort them
  47.                 #region Generate the base string for sigining
  48.                 var base_string = string.Empty;
  49.                 foreach (var item in mergerd_parameters)
  50.                 {
  51.                     base_string += item.Key + “=” + item.Value + “&”;
  52.                 }
  53.                 base_string = base_string.Remove(base_string.Length – 1);
  54.                 base_string = string.Concat(“GET&”, Uri.EscapeDataString(resource_url),
  55.                               “&”, Uri.EscapeDataString(base_string));
  56.                 #endregion Generate the base string for sigining
  57.                 #region Generate signature
  58.                 //Encrypt data
  59.                 var composite_key = string.Concat(Uri.EscapeDataString(oauth_consumer_secret),
  60.                             “&”, Uri.EscapeDataString(oauth_token_secret));
  61.                 string oauth_signature;
  62.                 using (HMACSHA1 hasher = new HMACSHA1(ASCIIEncoding.ASCII.GetBytes(composite_key)))
  63.                 {
  64.                     oauth_signature = Convert.ToBase64String(hasher.ComputeHash(ASCIIEncoding.ASCII.GetBytes(base_string)));
  65.                 }
  66.                 #endregion Generate signature
  67.                 #region Prepare authentication header and the request url
  68.                 var header_format = “OAuth oauth_nonce=\”{0}\”, oauth_signature_method=\”{1}\”, “ +
  69.                        “oauth_timestamp=\”{2}\”, oauth_consumer_key=\”{3}\”, “ +
  70.                        “oauth_token=\”{4}\”, oauth_signature=\”{5}\”, “ +
  71.                        “oauth_version=\”{6}\””;
  72.                 var auth_header = string.Format(_culture, header_format,
  73.                                         Uri.EscapeDataString(oauth_nonce),
  74.                                         Uri.EscapeDataString(oauth_signature_method),
  75.                                         Uri.EscapeDataString(oauth_timestamp),
  76.                                         Uri.EscapeDataString(oauth_consumer_key),
  77.                                         Uri.EscapeDataString(oauth_token),
  78.                                         Uri.EscapeDataString(oauth_signature),
  79.                                         Uri.EscapeDataString(oauth_version)
  80.                                 );
  81.                 //Disable exprect 100 continue header
  82.                 ServicePointManager.Expect100Continue = false;
  83.                 string resource_url_with_param = resource_url + “?”;
  84.                 foreach (var item in additional_parameters)
  85.                 {
  86.                     resource_url_with_param += item.Key + “=” + item.Value + “&”;
  87.                 }
  88.                 resource_url_with_param = resource_url_with_param.Remove(resource_url_with_param.Length – 1);
  89.                 #endregion Prepare authentication header and the request url
  90.                 #region Request Twitter API and process results
  91.                 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(resource_url_with_param);
  92.                 request.Headers.Add(“Authorization”, auth_header);
  93.                 request.Method = “GET”;
  94.                 request.ContentType = “application/x-www-form-urlencoded”;
  95.                 WebResponse response = request.GetResponse();
  96.                 string response_data;
  97.                 using (StreamReader reader = new StreamReader(response.GetResponseStream()))
  98.                 {
  99.                     response_data = reader.ReadToEnd();
  100.                     DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(List<Tweet>));
  101.                     using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(response_data)))
  102.                     {
  103.                         List<Tweet> tweet_collection = ser.ReadObject(ms) as List<Tweet>;
  104.                         foreach (var tweet in tweet_collection)
  105.                         {
  106.                                 //Do something here
  107.                         }
  108.                     }
  109.                 }
  110.                 #endregion Request Twitter API and process results
  111.             }
  112.             catch (Exception ex)
  113.             {
  114.                 throw ex;
  115.             }
  116.             

Twitter Entity
  1.         [DataContract]
  2.         public class Tweet
  3.         {
  4.             [DataMember]
  5.             public long id;
  6.             [DataMember]
  7.             public string id_str;
  8.             [DataMember]
  9.             public string text;
  10.             [DataMember]
  11.             public string created_at;
  12.         }

Note on the above sample:

oauth_parameters are the must provide parameters to sign the signature and connect to the API.
additional_parameters section includes all the parameters you need to customize the result set you gonna retrieve.

I have used a custom entity named Twitter to store the data retrieved from the json result object. This entity does not include all the result data. So you can add more fields as defined in the twitter entity documentation to read those values to the entity.

Happy Coding! Smile

Advertisements

2 thoughts on “Using Twitter API v1.1 with .net (oAuth) – no 3rd party libraries

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s