BCXAPI.Service._getJSONFromURL C# (CSharp) Method

_getJSONFromURL() private method

helper method to make a get request to basecamp. checks cache first if you've already received that response and checks with basecamp if you need to update your cache.
Will be thrown if you cannot refresh the basecamp token when it has expired URLs must end in .json Thrown when you exceed the ratelimit - will contain information on when you can retry
private _getJSONFromURL ( string url ) : dynamic
url string the api method endpoint being called
return dynamic
        private dynamic _getJSONFromURL(string url)
        {
            // ensure url ends with .json or .json?xxx
            if (!url.ToLower().EndsWith(".json") &&
                !(url.Contains("?") && url.ToLower().Substring(0, url.IndexOf("?")).EndsWith(".json")))
            {
                throw new ArgumentException("Invalid URL. URLs must end in .json", url);
            }

            string unique_id_to_hash = (_accessToken.access_token + url.ToLower());
            var cacheKey = unique_id_to_hash.CalculateMD5();
            try
            {
                //if in cache, check with server and if not modified then return original results
                string cached_results = (string)_cache.Get(cacheKey);
                if (cached_results != null)
                {
                    string if_none_match = (string)_cache.Get(cacheKey + "etag");
                    string if_modified_since = (string)_cache.Get(cacheKey + "lastModified");

                    System.Net.HttpWebRequest wr = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url);
                    wr.Method = "HEAD";
                    wr.Headers.Add(System.Net.HttpRequestHeader.Authorization, string.Format("Bearer {0}", _accessToken.access_token));
                    wr.UserAgent = _appNameAndContact;
                    if (!string.IsNullOrWhiteSpace(if_modified_since))
                    {
                        wr.IfModifiedSince = DateTime.Parse(if_modified_since);
                    }
                    if (!string.IsNullOrWhiteSpace(if_none_match))
                    {
                        wr.Headers["If-None-Match"] = if_none_match;
                    }
                    var resp = (System.Net.HttpWebResponse)wr.BetterGetResponse();//use extension to properly handle 304
                    if (resp.StatusCode == System.Net.HttpStatusCode.NotModified)
                    {
                        return Json.Decode(cached_results);
                    }
                }
            }
            catch
            {
                //if cache check fails just make the real request to basecamp
            }

            try
            {
                System.Net.HttpWebRequest wr = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url);
                wr.Method = "GET";
                wr.Headers.Add(System.Net.HttpRequestHeader.Authorization, string.Format("Bearer {0}", _accessToken.access_token));
                wr.UserAgent = _appNameAndContact;

                var resp = (System.Net.HttpWebResponse)wr.BetterGetResponse();
                if (resp.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    using (var sw = new System.IO.StreamReader(resp.GetResponseStream()))
                    {
                        var strResp = sw.ReadToEnd();
                        var json_results = Json.Decode(strResp);
                        var resp_etag = resp.Headers["ETag"] != null ? resp.Headers["ETag"] : null;
                        var resp_last_modified = resp.Headers["Last-Modified"] != null ? resp.Headers["Last-Modified"] : null;

                        if (resp_etag != null || resp_last_modified != null)
                        {
                            //cache it
                            if (!string.IsNullOrWhiteSpace(resp_etag))
                            {
                                _cache.Set(cacheKey + "etag", resp_etag);
                            }
                            if (!string.IsNullOrWhiteSpace(resp_last_modified))
                            {
                                _cache.Set(cacheKey + "lastModified", resp_last_modified);
                            }
                            if (!string.IsNullOrWhiteSpace(strResp))
                            {
                                _cache.Set(cacheKey, strResp);
                            }
                        }
                        return json_results;
                    }
                }
                else if (resp.StatusCode == (System.Net.HttpStatusCode)429)//too many requests
                {
                    throw new Exceptions.RateLimitExceededException(int.Parse(resp.Headers["Retry-After"]));
                }
                else if (resp.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                {
                    if (resp.Headers[System.Net.HttpResponseHeader.WwwAuthenticate] != null)
                    {
                        string www_auth = resp.Headers[System.Net.HttpResponseHeader.WwwAuthenticate];
                        int error_start = www_auth.LastIndexOf("error=\"token_expired\"");
                        if (error_start > -1)
                        {       //need to refresh token
                            throw new Exceptions.TokenExpired();
                        }
                    }

                    //throw an unauthorized exception if you get here
                    throw new Exceptions.UnauthorizedException();

                }
                else
                {
                    throw new Exceptions.GeneralAPIException("Try again later. Status code returned was " + (int)resp.StatusCode, (int)resp.StatusCode);
                }
            }
            catch (Exceptions.BaseException)
            {
                throw;
            }
            catch
            {
                return null;
            }
        }