public void GetUserInfos(Action <TwitterUserInfo> onRequestDone)
        {
            var content = string.Format("user_id={0}&screen_name={1}", OAuthEncoder.PercentEncode(_userId), OAuthEncoder.PercentEncode(_screenName));
            var taskUri = new Uri("https://api.twitter.com/1.1/users/show.json?" + content);
            var request = (HttpWebRequest)WebRequest.Create(taskUri);

            request.AutomaticDecompression = DecompressionMethods.GZip;
            request.Headers [HttpRequestHeader.Authorization] = OAuthAuthorizer.AuthorizeRequest(_oauthConfig, _oAuthToken, _oAuthTokenSecret, "GET", taskUri, null);

            TwitterUserInfo userInfos = null;

            request.BeginGetResponse(ar => {
                try {
                    var response = (HttpWebResponse)request.EndGetResponse(ar);
                    using (var stream = response.GetResponseStream())
                    {
                                                #if !WINDOWS
                        var jentry   = (JsonObject)JsonValue.Load(stream);
                        userInfos    = new TwitterUserInfo();
                        userInfos.Id = jentry["id_str"];
                        string name  = jentry["name"];
                        if (name.Contains(" "))
                        {
                            userInfos.Firstname = name.Substring(0, name.IndexOf(" "));
                            userInfos.Lastname  = name.Substring(name.IndexOf(" ") + 1);
                        }
                        else
                        {
                            userInfos.Firstname = name;
                        }
                        userInfos.City = jentry["location"];
                                                #endif
                    }
                } catch (WebException we) {
                    var response = we.Response as HttpWebResponse;
                    if (response != null)
                    {
                        switch (response.StatusCode)
                        {
                        case HttpStatusCode.Unauthorized:
                            // This is the case of sharing two keys
                            break;
                        }
                    }
                    Console.WriteLine(we);
                }
                finally{
                    if (onRequestDone != null)
                    {
                        onRequestDone(userInfos);
                    }
                }
            }, null);
        }
        /// <summary>
        /// Generate signature.
        /// </summary>
        /// <returns>Generated signature string.</returns>
        private string GenerateSignature()
        {
            string signatureBaseString = string.Format(
                CultureInfo.InvariantCulture,
                "{2}&{0}&{1}",
                OAuthEncoder.UrlEncode(RequestUriWithoutQuery.Normalize()),
                OAuthEncoder.UrlEncode(GetSignParameters()),
                Verb);

            string key = string.Format(
                CultureInfo.InvariantCulture,
                "{0}&{1}",
                OAuthEncoder.UrlEncode(ConsumerSecret.Value),
                OAuthEncoder.UrlEncode(TokenSecret.Value));

            return(_signatureManager.GetSignature(signatureBaseString, key));
        }
        /// <summary>
        /// Retrieve user data.
        /// </summary>
        /// <param name="screenName">User screen name or null for current logged user</param>
        /// <returns>Returns user data.</returns>
        public async Task <WeiboUser> GetUserAsync(string screenName = null)
        {
            string rawResult = null;

            try
            {
                Uri uri;
                if (screenName == null)
                {
                    uri = new Uri($"{BaseUrl}/users/show.json?uid={Uid}");
                }
                else
                {
                    uri = new Uri($"{BaseUrl}/users/show.json?screen_name={OAuthEncoder.UrlEncode(screenName)}");
                }

                WeiboOAuthRequest request = new WeiboOAuthRequest();
                rawResult = await request.ExecuteGetAsync(uri, _tokens);

                return(JsonConvert.DeserializeObject <WeiboUser>(rawResult));
            }
            catch (UserNotFoundException)
            {
                throw new UserNotFoundException(screenName);
            }
            catch
            {
                if (!string.IsNullOrEmpty(rawResult))
                {
                    var error = JsonConvert.DeserializeObject <WeiboError>(rawResult);

                    throw new WeiboException {
                              Error = error
                    };
                }

                throw;
            }
        }
        /// <summary>
        /// HTTP Post request to specified Uri.
        /// </summary>
        /// <param name="requestUri">Uri to make OAuth request.</param>
        /// <param name="tokens">Tokens to pass in request.</param>
        /// <param name="status">Status text.</param>
        /// <returns>String result.</returns>
        public async Task <WeiboStatus> ExecutePostAsync(Uri requestUri, WeiboOAuthTokens tokens, string status)
        {
            var contentDict = new Dictionary <string, string>();

            contentDict.Add("status", status);

            using (var formUrlEncodedContent = new FormUrlEncodedContent(contentDict))
            {
                using (var request = new HttpRequestMessage(HttpMethod.Post, requestUri))
                {
                    UriBuilder requestUriBuilder = new UriBuilder(request.RequestUri);
                    if (requestUriBuilder.Query.StartsWith("?"))
                    {
                        requestUriBuilder.Query = requestUriBuilder.Query.Substring(1) + "&access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken);
                    }
                    else
                    {
                        requestUriBuilder.Query = requestUriBuilder.Query + "access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken);
                    }

                    request.RequestUri = requestUriBuilder.Uri;

                    request.Content = formUrlEncodedContent;

                    using (var response = await _client.SendAsync(request).ConfigureAwait(false))
                    {
                        if (response.StatusCode == HttpStatusCode.OK)
                        {
                            return(JsonConvert.DeserializeObject <WeiboStatus>(await response.Content.ReadAsStringAsync().ConfigureAwait(false)));
                        }
                        else
                        {
                            response.ThrowIfNotValid();
                            ProcessError(await response.Content.ReadAsStringAsync().ConfigureAwait(false));
                            return(null);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// HTTP Get request to specified Uri.
        /// </summary>
        /// <param name="requestUri">Uri to make OAuth request.</param>
        /// <param name="tokens">Tokens to pass in request.</param>
        /// <returns>String result.</returns>
        public async Task <string> ExecuteGetAsync(Uri requestUri, WeiboOAuthTokens tokens)
        {
            using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUri))
            {
                UriBuilder requestUriBuilder = new UriBuilder(request.RequestUri);
                if (requestUriBuilder.Query.StartsWith("?"))
                {
                    requestUriBuilder.Query = requestUriBuilder.Query.Substring(1) + "&access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken);
                }
                else
                {
                    requestUriBuilder.Query = requestUriBuilder.Query + "?access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken);
                }

                request.RequestUri = requestUriBuilder.Uri;

                using (HttpResponseMessage response = await _client.SendAsync(request).ConfigureAwait(false))
                {
                    response.ThrowIfNotValid();
                    return(ProcessError(await response.Content.ReadAsStringAsync().ConfigureAwait(false)));
                }
            }
        }
        /// <summary>
        /// HTTP Post request to specified Uri.
        /// </summary>
        /// <param name="requestUri">Uri to make OAuth request.</param>
        /// <param name="tokens">Tokens to pass in request.</param>
        /// <param name="status">Status text.</param>
        /// <param name="content">Data to post to server.</param>
        /// <returns>String result.</returns>
        public async Task <WeiboStatus> ExecutePostMultipartAsync(Uri requestUri, WeiboOAuthTokens tokens, string status, byte[] content)
        {
            try
            {
                using (var multipartFormDataContent = new MultipartFormDataContent())
                {
                    using (var stringContent = new StringContent(status))
                    {
                        multipartFormDataContent.Add(stringContent, "status");
                        using (var byteContent = new ByteArrayContent(content))
                        {
                            // Somehow Weibo's backend requires a Filename field to work
                            byteContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                            {
                                FileName = "attachment", Name = "pic"
                            };
                            multipartFormDataContent.Add(byteContent, "pic");

                            using (var request = new HttpRequestMessage(HttpMethod.Post, requestUri))
                            {
                                UriBuilder requestUriBuilder = new UriBuilder(request.RequestUri);
                                if (requestUriBuilder.Query.StartsWith("?"))
                                {
                                    requestUriBuilder.Query = requestUriBuilder.Query.Substring(1) + "&access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken);
                                }
                                else
                                {
                                    requestUriBuilder.Query = requestUriBuilder.Query + "access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken);
                                }

                                request.RequestUri = requestUriBuilder.Uri;

                                request.Content = multipartFormDataContent;

                                using (var response = await _client.SendAsync(request).ConfigureAwait(false))
                                {
                                    if (response.StatusCode == HttpStatusCode.OK)
                                    {
                                        return(JsonConvert.DeserializeObject <WeiboStatus>(await response.Content.ReadAsStringAsync().ConfigureAwait(false)));
                                    }
                                    else
                                    {
                                        response.ThrowIfNotValid();
                                        ProcessError(await response.Content.ReadAsStringAsync().ConfigureAwait(false));
                                        return(null);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (ObjectDisposedException)
            {
                // known issue
                // http://stackoverflow.com/questions/39109060/httpmultipartformdatacontent-dispose-throws-objectdisposedexception
            }

            return(null);
        }
        /// <summary>
        /// Retrieve user timeline data with specific parser.
        /// </summary>
        /// <typeparam name="TSchema">Strong type for results.</typeparam>
        /// <param name="screenName">User screen name.</param>
        /// <param name="maxRecords">Upper record limit.</param>
        /// <param name="parser">Specific results parser.</param>
        /// <returns>Returns strongly typed list of results.</returns>
        public async Task <IEnumerable <TSchema> > GetUserTimeLineAsync <TSchema>(string screenName, int maxRecords, Toolkit.Parsers.IParser <TSchema> parser)
            where TSchema : Toolkit.Parsers.SchemaBase
        {
            string rawResult = null;

            try
            {
                var uri = new Uri($"{BaseUrl}/statuses/user_timeline.json?screen_name={OAuthEncoder.UrlEncode(screenName)}&count={maxRecords}");

                WeiboOAuthRequest request = new WeiboOAuthRequest();
                rawResult = await request.ExecuteGetAsync(uri, _tokens);

                var result = parser.Parse(rawResult);
                return(result
                       .Take(maxRecords)
                       .ToList());
            }
            catch (UserNotFoundException)
            {
                throw new UserNotFoundException(screenName);
            }
            catch
            {
                if (!string.IsNullOrEmpty(rawResult))
                {
                    var errors = JsonConvert.DeserializeObject <WeiboError>(rawResult);

                    throw new WeiboException {
                              Error = errors
                    };
                }

                throw;
            }
        }
        public void Share(string message, Action onRequestDone)
        {
            var content = string.Format("status={0}&trim_user=true&include_entities=true", OAuthEncoder.PercentEncode(message));
            var taskUri = new Uri("https://api.twitter.com/1/statuses/update.json");
            var client  = GetClient();

            client.Headers [HttpRequestHeader.Authorization] = OAuthAuthorizer.AuthorizeRequest(_oauthConfig, _oAuthToken, _oAuthTokenSecret, "POST", taskUri, content);

            try
            {
                client.UploadData(taskUri, "POST", Encoding.UTF8.GetBytes(content));
                if (onRequestDone != null)
                {
                    onRequestDone();
                }
            }
            catch (WebException ex)
            {
                Console.WriteLine("Error while posting on Twitter. Message: " + ex.Message);
            }
            finally
            {
                client.Dispose();
            }
        }