/// <summary> /// Asynchronous request for OAuth access token /// </summary> /// <param name="verifier">Verification token provided by Twitter after user authorizes (7-digit number for Pin authorization too)</param> /// <param name="oauthAccessTokenUrl">Access token URL</param> /// <param name="twitterCallbackUrl">URL for your app that Twitter redirects to after authorization (null for Pin authorization)</param> /// <param name="authenticationCompleteCallback">Callback to application after response completes (contains UserID and ScreenName)</param> public void GetAccessTokenAsync( string verifier, Uri oauthAccessTokenUrl, string twitterCallbackUrl, AuthAccessType authAccessType, Action <TwitterAsyncResponse <UserIdentifier> > authenticationCompleteCallback) { OAuthVerifier = verifier; var req = GetHttpGetRequest(oauthAccessTokenUrl, twitterCallbackUrl, authAccessType); req.BeginGetResponse( new AsyncCallback( ar => { string screenName = string.Empty; string userID = string.Empty; var twitterResponse = new TwitterAsyncResponse <UserIdentifier>(); try { var res = req.EndGetResponse(ar) as HttpWebResponse; string accessTokenResponse = GetHttpResponse(res); ProcessAccessTokenResponse(ref screenName, ref userID, accessTokenResponse); } catch (TwitterQueryException tqe) { twitterResponse.Status = TwitterErrorStatus.TwitterApiError; twitterResponse.Message = "Error while communicating with Twitter. Please see Error property for details."; twitterResponse.Exception = tqe; } catch (Exception ex) { twitterResponse.Status = TwitterErrorStatus.TwitterApiError; twitterResponse.Message = "Error during LINQ to Twitter processing. Please see Error property for details."; twitterResponse.Exception = ex; } finally { if (authenticationCompleteCallback != null) { twitterResponse.State = new UserIdentifier { ID = userID, UserID = userID, ScreenName = screenName }; authenticationCompleteCallback(twitterResponse); } } }), null); }
/// <summary> /// Asynchronous request for OAuth request token /// </summary> /// <param name="oauthRequestTokenUrl">Url to make initial request on</param> /// <param name="oauthAuthorizeUrl">Url to send user to for authorization</param> /// <param name="twitterCallbackUrl">Url for Twitter to redirect to after authorization (null for Pin authorization)</param> /// <param name="forceLogin">Should user be forced to log in to authorize this app</param> /// <param name="authorizationCallback">Lambda to let program perform redirect to authorization page</param> /// <param name="authenticationCompleteCallback">Lambda to invoke to let user know when authorization completes</param> public void GetRequestTokenAsync( Uri oauthRequestTokenUrl, Uri oauthAuthorizeUrl, string twitterCallbackUrl, bool forceLogin, Action <string> authorizationCallback, Action <TwitterAsyncResponse <object> > authenticationCompleteCallback) { HttpWebRequest req = GetHttpGetRequest(oauthRequestTokenUrl, twitterCallbackUrl); req.BeginGetResponse( new AsyncCallback( ar => { var twitterResponse = new TwitterAsyncResponse <object>(); try { string requestTokenResponse = string.Empty; var res = req.EndGetResponse(ar) as HttpWebResponse; using (var respStream = res.GetResponseStream()) using (var respReader = new StreamReader(respStream)) { requestTokenResponse = respReader.ReadToEnd(); } string authorizationUrl = PrepareAuthorizeUrl(oauthAuthorizeUrl.ToString(), forceLogin, requestTokenResponse); authorizationCallback(authorizationUrl); } catch (TwitterQueryException tqe) { twitterResponse.Status = TwitterErrorStatus.TwitterApiError; twitterResponse.Message = "Error while communicating with Twitter. Please see Error property for details."; twitterResponse.Error = tqe; } catch (Exception ex) { twitterResponse.Status = TwitterErrorStatus.TwitterApiError; twitterResponse.Message = "Error during LINQ to Twitter processing. Please see Error property for details."; twitterResponse.Error = ex; } finally { if (authenticationCompleteCallback != null) { authenticationCompleteCallback(twitterResponse); } } }), null); }
/// <summary> /// Posts asynchronously to Twitter for access token /// </summary> /// <param name="accessTokenUrl">Access token URL</param> /// <param name="postData">Post info</param> /// <param name="authorizationCompleteCallback">Invoked when request finishes</param> public void PostAccessTokenAsync(Request request, IDictionary <string, string> postData, Action <TwitterAsyncResponse <UserIdentifier> > authenticationCompleteCallback) { var accessTokenUrl = new Uri(request.FullUrl); var req = GetHttpPostRequest(accessTokenUrl); req.ContentType = "application/x-www-form-urlencoded"; var postBody = GatherPostData(postData); byte[] postDataBytes = Encoding.UTF8.GetBytes(postBody); #if SILVERLIGHT req.BeginGetRequestStream( new AsyncCallback( reqAr => { using (var requestStream = req.EndGetRequestStream(reqAr)) { requestStream.Write(postDataBytes, 0, postDataBytes.Length); } req.BeginGetResponse( new AsyncCallback( resAr => { string screenName = string.Empty; string userID = string.Empty; var twitterResponse = new TwitterAsyncResponse <UserIdentifier>(); try { string accessTokenResponse = string.Empty; var res = req.EndGetResponse(resAr) as HttpWebResponse; using (var respStream = res.GetResponseStream()) using (var respReader = new StreamReader(respStream)) { accessTokenResponse = respReader.ReadToEnd(); } ProcessAccessTokenResponse(ref screenName, ref userID, accessTokenResponse); } catch (TwitterQueryException tqe) { twitterResponse.Status = TwitterErrorStatus.TwitterApiError; twitterResponse.Message = "Error while communicating with Twitter. Please see Error property for details."; twitterResponse.Exception = tqe; } catch (Exception ex) { twitterResponse.Status = TwitterErrorStatus.TwitterApiError; twitterResponse.Message = "Error during LINQ to Twitter processing. Please see Error property for details."; twitterResponse.Exception = ex; } finally { if (authenticationCompleteCallback != null) { twitterResponse.State = new UserIdentifier { ID = userID, UserID = userID, ScreenName = screenName }; authenticationCompleteCallback(twitterResponse); } } }), null); }), null); #else Exception asyncException = null; using (var resetEvent = new ManualResetEvent(/*initialStateSignaled:*/ false)) { req.BeginGetRequestStream( new AsyncCallback( ar => { try { using (var requestStream = req.EndGetRequestStream(ar)) { requestStream.Write(postDataBytes, 0, postDataBytes.Length); } } catch (Exception ex) { asyncException = ex; } finally { resetEvent.Set(); } }), null); resetEvent.WaitOne(); } if (asyncException != null) { throw asyncException; } req.BeginGetResponse( new AsyncCallback( ar => { string screenName = string.Empty; string userID = string.Empty; var twitterResponse = new TwitterAsyncResponse <UserIdentifier>(); try { string accessTokenResponse = string.Empty; var res = req.EndGetResponse(ar) as HttpWebResponse; using (var respStream = res.GetResponseStream()) using (var respReader = new StreamReader(respStream)) { accessTokenResponse = respReader.ReadToEnd(); } ProcessAccessTokenResponse(ref screenName, ref userID, accessTokenResponse); } catch (TwitterQueryException tqe) { twitterResponse.Status = TwitterErrorStatus.TwitterApiError; twitterResponse.Message = "Error while communicating with Twitter. Please see Error property for details."; twitterResponse.Exception = tqe; } catch (Exception ex) { twitterResponse.Status = TwitterErrorStatus.TwitterApiError; twitterResponse.Message = "Error during LINQ to Twitter processing. Please see Error property for details."; twitterResponse.Exception = ex; } finally { if (authenticationCompleteCallback != null) { twitterResponse.State = new UserIdentifier { ID = userID, UserID = userID, ScreenName = screenName }; authenticationCompleteCallback(twitterResponse); } } }), null); #endif }
/// <summary> /// performs HTTP POST image byte array upload to Twitter /// </summary> /// <param name="image">byte array containing image to upload</param> /// <param name="url">url to upload to</param> /// <param name="fileName">name to pass to Twitter for the file</param> /// <param name="imageType">type of image: must be one of jpg, gif, or png</param> /// <param name="reqProc">Processes results of async requests</param> /// <returns>XML Response from Twitter</returns> public string PostTwitterImage <T>(byte[] image, Dictionary <string, string> parameters, string url, string fileName, string imageType, IRequestProcessor <T> reqProc) { string contentBoundaryBase = DateTime.Now.Ticks.ToString("x"); string beginContentBoundary = string.Format("--{0}\r\n", contentBoundaryBase); var contentDisposition = string.Format("Content-Disposition:form-data); name=\"image\"); filename=\"{0}\"\r\nContent-Type: image/{1}\r\n\r\n", fileName, imageType); var endContentBoundary = string.Format("\r\n--{0}--\r\n", contentBoundaryBase); var formDataSB = new StringBuilder(); if (parameters != null && parameters.Count > 0) { foreach (var param in parameters) { formDataSB.AppendFormat("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n", contentBoundaryBase, param.Key, param.Value); } } Encoding encoding = Encoding.GetEncoding("iso-8859-1"); string imageByteString = encoding.GetString(image, 0, image.Length); byte[] imageBytes = encoding.GetBytes( formDataSB.ToString() + beginContentBoundary + contentDisposition + imageByteString + endContentBoundary); string responseXml = string.Empty; string httpStatus = string.Empty; try { this.LastUrl = url; //Log WriteLog(url, "PostTwitterImage"); var req = this.AuthorizedClient.Post(url); //req.ServicePoint.Expect100Continue = false; req.ContentType = "multipart/form-data;boundary=" + contentBoundaryBase; //req.PreAuthenticate = true; req.AllowWriteStreamBuffering = true; req.ContentLength = imageBytes.Length; Exception asyncException = null; var resetEvent = new ManualResetEvent(initialState: false); req.BeginGetRequestStream( new AsyncCallback( ar => { try { using (var reqStream = req.EndGetRequestStream(ar)) { int offset = 0; int bufferSize = 4096; int lastPercentage = 0; while (offset < imageBytes.Length) { int bytesLeft = imageBytes.Length - offset; if (bytesLeft < bufferSize) { reqStream.Write(imageBytes, offset, bytesLeft); } else { reqStream.Write(imageBytes, offset, bufferSize); } offset += bufferSize; int percentComplete = (int)((double)offset / (double)imageBytes.Length * 100); // since we still need to get the response later // in the algorithm, interpolate the results to // give user a more accurate picture of completion. // i.e. we don't want to shoot up to 100% here when // we know there is more processing to do. lastPercentage = percentComplete >= 98 ? 100 - ((98 - lastPercentage) / 2) : percentComplete; OnUploadProgressChanged(lastPercentage); } reqStream.Flush(); } } catch (Exception ex) { asyncException = ex; } finally { resetEvent.Set(); } }), null); resetEvent.WaitOne(); if (asyncException != null) { throw asyncException; } resetEvent.Reset(); req.BeginGetResponse( new AsyncCallback( ar => { try { using (var res = req.EndGetResponse(ar) as HttpWebResponse) { httpStatus = res.Headers["Status"]; responseXml = GetTwitterResponse(res); if (AsyncCallback != null) { List <T> responseObj = reqProc.ProcessResults(responseXml); var asyncResp = new TwitterAsyncResponse <T>(); asyncResp.State = responseObj.FirstOrDefault(); (AsyncCallback as Action <TwitterAsyncResponse <T> >)(asyncResp); } // almost done OnUploadProgressChanged(99); } } catch (Exception ex) { asyncException = ex; } finally { resetEvent.Set(); } }), null); resetEvent.WaitOne(); if (asyncException != null) { throw asyncException; } } catch (WebException wex) { var twitterQueryEx = CreateTwitterQueryException(wex); throw twitterQueryEx; } // make sure the caller knows it's done OnUploadProgressChanged(100); CheckResultsForTwitterError(responseXml, httpStatus); return(responseXml); }
/// <summary> /// utility method to perform HTTP POST for Twitter requests with side-effects /// </summary> /// <param name="url">URL of request</param> /// <param name="parameters">parameters to post</param> /// <param name="reqProc">Processes results of async requests</param> /// <returns>XML response from Twitter</returns> public string ExecuteTwitter <T>(string url, Dictionary <string, string> parameters, IRequestProcessor <T> reqProc) { string httpStatus = string.Empty; string responseXml = string.Empty; // Oddly, we add the parameters both to the URI's query string and the POST entity Uri requestUri = Utilities.AppendQueryString(new Uri(url), parameters); try { this.LastUrl = requestUri.AbsoluteUri; //Log WriteLog(url, "ExecuteTwitter"); #if SILVERLIGHT HttpWebRequest req = AuthorizedClient.PostAsync(url, parameters); req.BeginGetResponse( new AsyncCallback( ar => { var resp = req.EndGetResponse(ar) as HttpWebResponse; responseXml = GetTwitterResponse(resp); CheckResultsForTwitterError(responseXml, httpStatus); if (AsyncCallback != null) { List <T> responseObj = reqProc.ProcessResults(responseXml); var asyncResp = new TwitterAsyncResponse <T>(); asyncResp.State = responseObj.FirstOrDefault(); (AsyncCallback as Action <TwitterAsyncResponse <T> >)(asyncResp); } }), null); #else if (AsyncCallback != null) { HttpWebRequest req = AuthorizedClient.PostAsync(url, parameters); req.BeginGetResponse( new AsyncCallback( ar => { var resp = req.EndGetResponse(ar) as HttpWebResponse; responseXml = GetTwitterResponse(resp); CheckResultsForTwitterError(responseXml, httpStatus); List <T> responseObj = reqProc.ProcessResults(responseXml); var asyncResp = new TwitterAsyncResponse <T>(); asyncResp.State = responseObj.FirstOrDefault(); (AsyncCallback as Action <TwitterAsyncResponse <T> >)(asyncResp); }), null); } else { using (var resp = this.AuthorizedClient.Post(url, parameters)) { httpStatus = resp.Headers["Status"]; responseXml = GetTwitterResponse(resp); } } #endif } catch (WebException wex) { var twitterQueryEx = CreateTwitterQueryException(wex); throw twitterQueryEx; } return(responseXml); }