Esempio n. 1
0
        // flag below because it's a *pain* to break inside this routine unless it was intended.
        // we want the exceptions from here to considered the root for the debugger to land.
        /// <summary>
        /// Executes a JSON based REST rpc call
        /// </summary>
        /// <param name="baseUrl">The url to use</param>
        /// <param name="args">Arguments to append to the url, represented as a simplified json object (only holds scalar values)</param>
        /// <param name="payloadJson">The JSON to send as part of the request body</param>
        /// <param name="timestampField">If specificed, indicates a field to insert a timestamp into. This timestamp represents the time the object was last fetched (either from the file cache or from the server)</param>
        /// <param name="httpMethod">Set this to use a custom HTTP method (like DELETE)</param>
        /// <param name="fixupResponse">An optional custom routine that can massage the JSON returned into a more acceptable form. This is useful if the data from the server needs to be adjusted prior to anything else.</param>
        /// <param name="fixupError">An optional custom routine that can massage the JSON error object returned into a more acceptable form. This is useful if the error from the server needs to be adjusted prior to anything else. You may need to specify this to get the <see cref="JsonRpcException" /> to work properly.</param>
        /// <param name="cache">Indicates whether or not a file cache should be used for requests. The in memory cache is only on a per-thread basis. The file cache stores by URL and is global. The cache is very aggressive.</param>
        /// <returns>The JSON returned in the response body.</returns>
        /// <remarks>Exceptions are expected to have JSON in the response body. This JSON is used as the data for the exception. The exception thrown currently uses a simple heuristic to figure out what the relevant fields are. Usually however, you'll get the data using the Json property of it.</remarks>
        //[DebuggerNonUserCode]
        public static object Invoke(
            string baseUrl,
            IDictionary <string, object> args = null,
            object payloadJson    = null,
            string timestampField = null,
            string httpMethod     = null,
            Func <object, object> fixupResponse = null,
            Func <object, object> fixupError    = null,
            JsonRpcCacheLevel cache             = JsonRpcCacheLevel.Conservative)
        {
            HttpWebRequest  wreq = null;
            HttpWebResponse wrsp = null;
            var             url  = GetInvocationUrl(baseUrl, args);

            wreq                   = WebRequest.Create(url) as HttpWebRequest;
            wreq.KeepAlive         = true;
            wreq.Pipelined         = true;
            wreq.AllowAutoRedirect = true;
            RequestCacheLevel cp = RequestCacheLevel.Default;

            switch (cache)
            {
            case JsonRpcCacheLevel.None:
                cp = RequestCacheLevel.NoCacheNoStore;
                break;

            case JsonRpcCacheLevel.Conservative:
                cp = RequestCacheLevel.Revalidate;
                break;

            case JsonRpcCacheLevel.Aggressive:
                cp = RequestCacheLevel.CacheIfAvailable;
                break;
            }
            wreq.CachePolicy = new RequestCachePolicy(cp);
            if (null != payloadJson)
            {
                if (string.IsNullOrEmpty(httpMethod))
                {
                    wreq.Method = "POST";
                }
                else
                {
                    wreq.Method = httpMethod;
                }
                wreq.ContentType = "application/json";
                using (var sw = new StreamWriter(wreq.GetRequestStream()))
                {
                    JsonObject.WriteTo(payloadJson, sw, null);
                    sw.Flush();
                }
            }
            else if (string.IsNullOrEmpty(httpMethod))
            {
                wreq.Method = "GET";
            }
            else
            {
                wreq.Method = httpMethod;
            }

            try
            {
                wrsp = wreq.GetResponse() as HttpWebResponse;
                if (wrsp.StatusCode != HttpStatusCode.NoContent)
                {
                    using (var reader = JsonTextReader.CreateFrom(new StreamReader(wrsp.GetResponseStream())))
                    {
                        object data = null;
                        try
                        {
                            data = reader.ParseSubtree();
                        }
                        catch (ExpectingException eex)
                        {
                            var ex = new JsonObject();
                            ex.Add("status_code", -39);
                            ex.Add("status_message", "Malformed or empty JSON data returned: " + eex.Message);
                            ex.Add("http_status", (int)wrsp.StatusCode);
                            ex.Add("http_status_message", wrsp.StatusDescription);
                            throw new JsonRpcException(ex);
                        }
                        if (null != fixupResponse)
                        {
                            data = fixupResponse(data);
                        }
                        if (!string.IsNullOrEmpty(timestampField))
                        {
                            var d = data as IDictionary <string, object>;
                            if (null != d)
                            {
                                DateTime dt = DateTime.UtcNow;
                                d.Add(timestampField, dt.ToString("O"));
                            }
                        }
                        return(data);
                    }
                }
                else
                {
                    return(null);
                }
            }
            catch (Exception ex)
            {
                var wex = ex as WebException;
                if (null != wex)
                {
                    if (null == wrsp)
                    {
                        wrsp = wex.Response as HttpWebResponse;
                    }
                    if (null != wrsp)
                    {
                        using (var reader = JsonTextReader.CreateFrom(new StreamReader(wrsp.GetResponseStream())))
                        {
                            object data = null;
                            try
                            {
                                data = reader.ParseSubtree();
                            }
                            catch (ExpectingException eex)
                            {
                                var jex = new JsonObject();

                                jex.Add("status_code", -39);
                                jex.Add("status_message", "Malformed or empty JSON data returned: " + eex.Message);
                                jex.Add("http_status", (int)wrsp.StatusCode);
                                jex.Add("http_status_message", wrsp.StatusDescription);
                                data = jex;
                            }
                            if (null != fixupError)
                            {
                                data = fixupError(data);
                            }
                            var d = data as IDictionary <string, object>;

                            if (!string.IsNullOrEmpty(timestampField))
                            {
                                if (null != d)
                                {
                                    d.Add(timestampField, DateTime.UtcNow.ToString("O"));
                                }
                            }

                            if (null != d)
                            {
                                throw new JsonRpcException(d);
                            }
                        }
                    }
                }
                throw;
            }
        }