/// <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); }