예제 #1
0
        /// <summary>
        /// Requests the specified request method.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="requestMethod">The request method.</param>
        /// <param name="url">The URL.</param>
        /// <param name="requestData">The request data.</param>
        /// <param name="options">The options.</param>
        /// <returns>System.Threading.Tasks.Task&lt;T&gt;.</returns>
        /// <exception cref="System.Exception">ClientId and ClientSecret is not set</exception>
        /// <exception cref="PodioInvalidGrantException"></exception>
        /// <exception cref="PodioBadRequestException"></exception>
        /// <exception cref="PodioAuthorizationException"></exception>
        /// <exception cref="PodioForbiddenException"></exception>
        /// <exception cref="PodioNotFoundException"></exception>
        /// <exception cref="PodioConflictException"></exception>
        /// <exception cref="PodioGoneException"></exception>
        /// <exception cref="PodioRateLimitException"></exception>
        /// <exception cref="PodioServerException"></exception>
        /// <exception cref="PodioUnavailableException"></exception>
        /// <exception cref="PodioException"></exception>
        private async Task <T> RequestAsync <T>(RequestMethod requestMethod, string url, dynamic requestData, dynamic options = null) where T : new()
        {
            Dictionary <string, string> requestHeaders = new Dictionary <string, string>();
            var    data        = new List <string>();
            string httpMethod  = string.Empty;
            string originalUrl = url;

            url = this.ApiUrl + url;

            //To use url other than api.podio.com, ex file download from files.podio.com
            if (options != null && options.ContainsKey("url"))
            {
                url = options["url"];
            }

            if (string.IsNullOrEmpty(ClientId) || string.IsNullOrEmpty(ClientSecret))
            {
                throw new Exception("ClientId and ClientSecret is not set");
            }

            switch (requestMethod.ToString())
            {
            case "GET":
                httpMethod = "GET";
                requestHeaders["Content-type"] = "application/x-www-form-urlencoded";
                if (requestData != null)
                {
                    string query = EncodeAttributes(requestData);
                    url = url + "?" + query;
                }
                requestHeaders["Content-length"] = "0";
                break;

            case "DELETE":
                httpMethod = "DELETE";
                requestHeaders["Content-type"] = "application/x-www-form-urlencoded";
                if (requestData != null)
                {
                    string query = EncodeAttributes(requestData);
                    url = url + "?" + query;
                }
                requestHeaders["Content-length"] = "0";
                break;

            case "POST":
                httpMethod = "POST";
                if (options != null && options.ContainsKey("upload") && options["upload"])
                {
                    requestHeaders["Content-type"] = "multipart/form-data";
                    data.Add("file");
                }
                else if (options != null && options.ContainsKey("oauth_request") && options["oauth_request"])
                {
                    data.Add("oauth");
                    requestHeaders["Content-type"] = "application/x-www-form-urlencoded";
                }
                else
                {
                    requestHeaders["Content-type"] = "application/json";
                    data.Add("post");
                }
                break;

            case "PUT":
                httpMethod = "PUT";
                requestHeaders["Content-type"] = "application/json";
                data.Add("put");
                break;
            }

            if (OAuth != null && !string.IsNullOrEmpty(OAuth.AccessToken))
            {
                requestHeaders["Authorization"] = "OAuth2 " + OAuth.AccessToken;
                if (options != null && options.ContainsKey("oauth_request") && options["oauth_request"])
                {
                    requestHeaders.Remove("Authorization");
                }
            }
            else
            {
                requestHeaders.Remove("Authorization");
            }

            if (options != null && options.ContainsKey("file_download") && options["file_download"])
            {
                requestHeaders["Accept"] = "*/*";
            }
            else
            {
                requestHeaders["Accept"] = "application/json";
            }

            var request = (HttpWebRequest)WebRequest.Create(url);

            request.Method = httpMethod;

            PodioResponse podioResponse   = new PodioResponse();
            var           responseHeaders = new Dictionary <string, string>(StringComparer.CurrentCultureIgnoreCase);
            var           responseObject  = new T();

            if (requestHeaders.Any())
            {
                if (requestHeaders.ContainsKey("Accept"))
                {
                    request.Accept = requestHeaders["Accept"];
                }
                if (requestHeaders.ContainsKey("Content-type"))
                {
                    request.ContentType = requestHeaders["Content-type"];
                }
                if (requestHeaders.ContainsKey("Authorization"))
                {
                    request.Headers["Authorization"] = requestHeaders["Authorization"];
                }
            }
            if (data.Any())
            {
                foreach (string item in data)
                {
                    if (item == "file")
                    {
                        await AddFileToRequestStream(requestData.filePath, requestData.fileName, requestData.mimeType, request);
                    }
                    else if (item == "oauth")
                    {
                        await WriteToRequestStream(EncodeAttributes(requestData), request);
                    }
                    else
                    {
                        await WriteToRequestStream(requestData, request);
                    }
                }
            }

            try
            {
                WebResponse webResponse = await Task.Factory.FromAsync <WebResponse>(request.BeginGetResponse, request.EndGetResponse, request);

                using (webResponse)
                {
                    podioResponse.Status = (int)((HttpWebResponse)webResponse).StatusCode;
                    foreach (string key in webResponse.Headers.AllKeys)
                    {
                        responseHeaders.Add(key, webResponse.Headers[key]);
                    }

                    if (options != null && options.ContainsKey("file_download"))
                    {
                        using (var memoryStream = new MemoryStream())
                        {
                            var fileResponse = new FileResponse();
                            webResponse.GetResponseStream().CopyTo(memoryStream);
                            fileResponse.FileContents  = memoryStream.ToArray();
                            fileResponse.ContentType   = webResponse.ContentType;
                            fileResponse.ContentLength = webResponse.ContentLength;
                            return((T)fileResponse.ChangeType <T>());
                        }
                    }
                    else if (options != null && options.ContainsKey("return_raw"))
                    {
                        using (StreamReader sr = new StreamReader(webResponse.GetResponseStream()))
                        {
                            podioResponse.Body = sr.ReadToEnd();
                            return(podioResponse.Body);
                        }
                    }
                    else
                    {
                        using (StreamReader sr = new StreamReader(webResponse.GetResponseStream()))
                        {
                            podioResponse.Body = sr.ReadToEnd();
                        }
                    }
                    podioResponse.Headers = responseHeaders;
                }
            }
            catch (WebException e)
            {
                using (WebResponse response = e.Response)
                {
                    podioResponse.Status = (int)((HttpWebResponse)response).StatusCode;
                    foreach (string key in response.Headers.AllKeys)
                    {
                        responseHeaders.Add(key, response.Headers[key]);
                    }

                    using (StreamReader sr = new StreamReader(response.GetResponseStream()))
                    {
                        podioResponse.Body = sr.ReadToEnd();
                    }
                    podioResponse.Headers = responseHeaders;
                }
            }


            if (podioResponse.Headers.ContainsKey("X-Rate-Limit-Remaining"))
            {
                RateLimitRemaining = int.Parse(podioResponse.Headers["X-Rate-Limit-Remaining"]);
            }
            if (podioResponse.Headers.ContainsKey("X-Rate-Limit-Limit"))
            {
                RateLimit = int.Parse(podioResponse.Headers["X-Rate-Limit-Limit"]);
            }

            PodioError podioError = new PodioError();

            if (podioResponse.Status >= 400)
            {
                podioError = JSONSerializer.Deserilaize <PodioError>(podioResponse.Body);
            }

            switch (podioResponse.Status)
            {
            case 200:
            case 201:
                responseObject = JSONSerializer.Deserilaize <T>(podioResponse.Body);
                break;

            case 204:
                responseObject = default(T);
                break;

            case 400:
                if (podioError.Error == "invalid_grant")
                {
                    //Reset auth info
                    OAuth = new PodioOAuth();
                    throw new PodioInvalidGrantException(podioResponse.Status, podioError);
                }
                else
                {
                    throw new PodioBadRequestException(podioResponse.Status, podioError);
                }

            case 401:
                if (podioError.ErrorDescription == "expired_token" || podioError.Error == "invalid_token")
                {
                    if (!string.IsNullOrEmpty(OAuth.RefreshToken))
                    {
                        //Refresh access token
                        var authInfo = await RefreshAccessTokenAsync();

                        if (authInfo != null && !string.IsNullOrEmpty(authInfo.AccessToken))
                        {
                            responseObject = await RequestAsync <T>(requestMethod, originalUrl, requestData, options);
                        }
                    }
                    else
                    {
                        throw new PodioAuthorizationException(podioResponse.Status, podioError);
                    }
                }
                break;

            case 403:
                throw new PodioForbiddenException(podioResponse.Status, podioError);

            case 404:
                throw new PodioNotFoundException(podioResponse.Status, podioError);

            case 409:
                throw new PodioConflictException(podioResponse.Status, podioError);

            case 410:
                throw new PodioGoneException(podioResponse.Status, podioError);

            case 420:
                throw new PodioRateLimitException(podioResponse.Status, podioError);

            case 500:
                throw new PodioServerException(podioResponse.Status, podioError);

            case 502:
            case 503:
            case 504:
                throw new PodioUnavailableException(podioResponse.Status, podioError);

            default:
                throw new PodioException(podioResponse.Status, podioError);
            }

            return(responseObject);
        }