Posting Twitter Status Update from Windows Phone

In my post Twitter in a Windows Phone 7 App across at BuildMobile I covered how to authenticate against Twitter using OAuth1. What I didn’t cover in that post is how you can then use the Access Token to interact with the Twitter API. In this post I’ll show you how you can post a status update to Twitter from your Windows Phone application.

Let’s start by creating a TextBox and a Button. Obviously the TextBox will be for the status to be posted and the Button will be to submit the Tweet:

<TextBox x_Name="TweetText"/>
<Button Content="Tweet" Click="TweetClick" />

Some points/gotchas to note:

* The user will have had to been authenticated prior to hitting this button or the post will fail.
* Twitter does not allow the same message to be repeatedly posted – if during testing you attempt to post the same test message, don’t be surprised if it fails!
* If your Windows Phone application is going to post messages to Twitter it need to request Read/Write (and potentially Direct Message) permissions to the users Twitter account.  This is not enabled by default when you create the application in Twitter, you have to go to the Settings tab and adjust the Application Type eg

image

Essentially in order to post a status update to Twitter you simply need to create the appropriately formed HttpWebRequest. The request will be a POST and you’ll include “status=<new status>” as the body of the POST. The url of the request will be “statuses/update.json” off the Twitter base API url. Note that the .json indicates that the response will come back as json. You can specify .xml if you’d prefer an XML response.

private void TweetClick(object sender, RoutedEventArgs e) {
    var requestParameters = new Dictionary<string, string>();
    var body = "status=" + UrlEncode(this.TweetText.Text);
    requestParameters[OAuthPostBodyKey] = body;

    var postUrl = "http://api.twitter.com/1/statuses/update.json";
    var request = CreateRequest("POST", postUrl, requestParameters);
    request.BeginGetRequestStream(reqresult => {
        var req = reqresult.AsyncState as HttpWebRequest;
        using (var strm = req.EndGetRequestStream(reqresult))
        using (var writer = new StreamWriter(strm)) {
            writer.Write(body);
        }
        req.BeginGetResponse(result => {
            try {
                var req2 = result.AsyncState as HttpWebRequest;
                if (req2 == null) throw new ArgumentNullException("result", "Request parameter is null");
                using (var resp = req.EndGetResponse(result))
                using (var strm = resp.GetResponseStream())
                using (var reader = new StreamReader(strm)) {
                    var responseText = reader.ReadToEnd();

                  Dispatcher.BeginInvoke(() => MessageBox.Show("Tweeted!"));
                }
            }
            catch {
                Dispatcher.BeginInvoke(() => MessageBox.Show("Unable to tweet"));
            }
        }, req);
    }, request);
}

If you followed the code on my BuildMobile post there are a couple of changes we need to make in order to support posting. The first enables us to pass in a Dictionary into the CreateRequest method. This is so that we can specify the body of the post which needs to be used in the calculation of the signature.

private WebRequest CreateRequest(string httpMethod, string requestUrl, IDictionary<string, string> requestParameters = null) {
    if (requestParameters == null) {
        requestParameters = new Dictionary<string, string>();
    }
    var secret = "";
    if (!string.IsNullOrEmpty(token)) {
        requestParameters[OAuthTokenKey] = token;
    secret = tokenSecret;
    }
    if (!string.IsNullOrEmpty(pin)) {
        requestParameters[OAuthVerifierKey] = pin;
    }
    var url = new Uri(requestUrl);
    var normalizedUrl = requestUrl;
    if (!string.IsNullOrEmpty(url.Query)) {
    normalizedUrl = requestUrl.Replace(url.Query, "");
    }
    var signature = GenerateSignature(httpMethod, normalizedUrl, url.Query, requestParameters, secret);
    requestParameters[OAuthSignatureKey] = UrlEncode(signature);

    var request = WebRequest.CreateHttp(normalizedUrl);
    request.Method = httpMethod;
    request.Headers[HttpRequestHeader.Authorization] = GenerateAuthorizationHeader(requestParameters);
    return request;
}

The other change we need to make is to the GenerateAuthorizationHeader method. Because the status itself will be passed as a form parameter in the body of the POST it shouldn’t be included in the authorization header. As such we need to modify the method to ignore any parameters that do not begin with “oauth_”.

public static string GenerateAuthorizationHeader(IDictionary<string, string> requestParameters)
{     var paras = new StringBuilder();     foreach (var param in requestParameters)     {
        if (!param.Key.StartsWith("oauth_")) continue;
        if (paras.Length > 0) paras.Append(",");         paras.Append(param.Key + "="" + param.Value + """);     }     return "OAuth " + paras;
}

 

And there we have it. Code that will enable your Windows Phone application to post to Twitter.

Leave a comment