예제 #1
0
        /// <summary>
        /// Executes an asynchronous request to the given resource and deserializes the response to an object of T.
        /// </summary>
        /// <typeparam name="T">The type to deserialize to.</typeparam>
        /// <param name="restRequest">The RestRequest to execute.</param>
        /// <returns>An object of T.</returns>
        public async Task <T> ExecuteAsync <T>(RestRequest restRequest) where T : class
        {
            T   result = null;
            var url    = restRequest.GetFormattedResource(BaseUrl);

            if (string.IsNullOrWhiteSpace(restRequest.DateFormat) && !string.IsNullOrWhiteSpace(DateFormat))
            {
                restRequest.DateFormat = DateFormat;
            }

            var handler = new CompressedHttpClientHandler {
                AllowAutoRedirect = true
            };

            _client = new HttpClient(handler);

            if (!string.IsNullOrWhiteSpace(UserAgent))
            {
                _client.DefaultRequestHeaders.Add("user-agent", UserAgent);
            }

            var message = new HttpRequestMessage(restRequest.Method, new Uri(restRequest.Resource, UriKind.RelativeOrAbsolute));

            foreach (var header in Headers)
            {
                message.Headers.Add(header.Key, header.Value);
            }

            if (restRequest.Method == HttpMethod.Post || restRequest.Method == HttpMethod.Put)
            {
                var contentString = new StringContent(restRequest.GetRequestBody(), Encoding.UTF8, restRequest.GetContentType());
                message.Content = contentString;
            }

            HttpResponseMessage response = null;

            response = await _client.SendAsync(message);

            response.EnsureSuccessStatusCode();

            var responseContent = await response.Content.ReadAsStringAsync();

            //TODO: Handle Error
            if (response.Content.Headers.ContentType.MediaType == "application/xml")

            {
                // RWM: IDEA - The DataContractSerializer doesn't like attributes, but will handle everything else.
                // So instead of trying to mess with a double-conversion to JSON and then to the Object, we'll just turn the attributes
                // into elements, and sort the elements into alphabetical order so the DataContracterializer doesn't crap itself.

                // On post, use a C# attribute to specify if a property is an XML attribute, DataContractSerialize to XML, then
                // query the object for [XmlAttribute] attributes and move them from elements to attributes using code similar to below.
                // If the POST request requires the attributes in a certain order, oh well. Shouldn't have used PHP :P.

                XElement root    = XElement.Parse(responseContent);
                XElement newRoot = (XElement)Transform(restRequest.IgnoreRootElement ? root.Descendants().First() : root, restRequest);

                using (var memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(newRoot.ToString())))
                {
                    var settings = new XmlReaderSettings {
                        IgnoreWhitespace = true
                    };
                    using (var reader = XmlReader.Create(memoryStream, settings))
                    {
                        try
                        {
                            var serializer = new DataContractSerializer(typeof(T));
                            result = serializer.ReadObject(reader) as T;
                        }
                        catch (SerializationException ex)
                        {
                            throw new PortableRestException(string.Format("The serializer failed on node '{0}'", reader.Name), reader.Name, ex);
                        }
                    }
                }
            }
            else
            {
                result = JsonConvert.DeserializeObject <T>(responseContent);
            }

            return(result);
        }