/// <summary>
        /// Reads a response from the service and converts it to the specified return type.
        /// </summary>
        /// <param name="result">The result object which contains information about which operation was performed.</param>
        /// <param name="returnType">Type which should be returned.</param>
        /// <returns></returns>
        /// <exception cref="OpenRiaServices.DomainServices.Client.DomainOperationException">On server errors which did not produce expected output</exception>
        /// <exception cref="FaultException{DomainServiceFault}">If server returned a DomainServiceFault</exception>
        private object ReadResponse(WebApiDomainClientAsyncResult result, Type returnType)
        {
            HttpResponseMessage response = ((Task<HttpResponseMessage>)result.InnerAsyncResult).Result;

            if (!response.IsSuccessStatusCode)
            {
                var message = string.Format(Resources.DomainClient_UnexpectedHttpStatusCode, (int)response.StatusCode, response.StatusCode);

                if (response.StatusCode == HttpStatusCode.BadRequest)
                    throw new DomainOperationException(message, OperationErrorStatus.NotSupported, (int)response.StatusCode, null);
                else if (response.StatusCode == HttpStatusCode.Unauthorized)
                    throw new DomainOperationException(message, OperationErrorStatus.Unauthorized, (int)response.StatusCode, null);
                else
                    throw new DomainOperationException(message, OperationErrorStatus.ServerError, (int)response.StatusCode, null);
            }

            var ms = response.Content.ReadAsStreamAsync().Result;
            using (var reader = System.Xml.XmlDictionaryReader.CreateBinaryReader(ms, System.Xml.XmlDictionaryReaderQuotas.Max))
            {
                reader.Read();

                // Domain Fault
                if (reader.LocalName == "Fault")
                {
                    throw ReadFaultException(reader, result.OperationName);
                }
                else
                {
                    // Validate that we are no on ****Response node
                    VerifyReaderIsAtNode(reader, result.OperationName, "Response");
                    reader.ReadStartElement(); // Read to next which should be ****Result

                    // Validate that we are no on ****Result node
                    VerifyReaderIsAtNode(reader, result.OperationName, "Result");

                    var serializer = GetSerializer(returnType);
                    return serializer.ReadObject(reader, verifyObjectName: false);
                }
            }
        }
        /// <summary>
        /// Initiates a GET request for the given operation and return the server respose (as a task).
        /// </summary>
        /// <param name="result">The result object which contains information about which operation was performed.</param>
        /// <param name="parameters">The parameters to the server method, or <c>null</c> if no parameters.</param>
        /// <param name="queryOptions">The query options if any.</param>
        /// <returns></returns>
        private Task<HttpResponseMessage> GetAsync(WebApiDomainClientAsyncResult result, IDictionary<string, object> parameters, IList<ServiceQueryPart> queryOptions)
        {
            int i = 0;
            var uriBuilder = new StringBuilder();
            uriBuilder.Append(result.OperationName);

            // Parameters
            if (parameters != null && parameters.Count > 0)
            {
                foreach (var param in parameters)
                {
                    uriBuilder.Append(i++ == 0 ? '?' : '&');
                    uriBuilder.Append(Uri.EscapeDataString(param.Key));
                    uriBuilder.Append("=");
                    if (param.Value != null)
                    {
                        var value = QueryStringConverter.ConvertValueToString(param.Value, param.Value.GetType());
                        uriBuilder.Append(Uri.EscapeDataString(value));
                    }
                }
            }

            // Query options
            if (queryOptions != null && queryOptions.Count > 0)
            {
                foreach (var queryPart in queryOptions)
                {
                    uriBuilder.Append(i++ == 0 ? "?$" : "&$");
                    uriBuilder.Append(queryPart.QueryOperator);
                    uriBuilder.Append("=");
                    uriBuilder.Append(Uri.EscapeDataString(queryPart.Expression));
                }
            }

            // TODO: Switch to POST if uri becomes to long, we can do so by returning nul ...l
            var uri = uriBuilder.ToString();
            return HttpClient.GetAsync(uri);
        }
        /// <summary>
        /// Initiates a POST request for the given operation and return the server respose (as a task).
        /// </summary>
        /// <param name="result">The result object which contains information about which operation was performed.</param>
        /// <param name="parameters">The parameters to the server method, or <c>null</c> if no parameters.</param>
        /// <param name="queryOptions">The query options if any.</param>
        /// <returns></returns>
        private Task<HttpResponseMessage> PostAsync(WebApiDomainClientAsyncResult result, IDictionary<string, object> parameters, IList<ServiceQueryPart> queryOptions)
        {
            var ms = new System.IO.MemoryStream();
            var writer = System.Xml.XmlDictionaryWriter.CreateBinaryWriter(ms);

            // Write message
            {
                var rootNamespace = "http://tempuri.org/";
                bool hasQueryOptions = (queryOptions != null && queryOptions.Count > 0);

                if (hasQueryOptions)
                {
                    writer.WriteStartElement("MessageRoot");
                    writer.WriteStartElement("QueryOptions");
                    foreach (var queryOption in queryOptions)
                    {
                        writer.WriteStartElement("QueryOption");
                        writer.WriteAttributeString("Name", queryOption.QueryOperator);
                        writer.WriteAttributeString("Value", queryOption.Expression);
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                }
                writer.WriteStartElement(result.OperationName, rootNamespace); // <OperationName>

                // Write all parameters
                if (parameters != null && parameters.Count > 0)
                {
                    foreach (var param in parameters)
                    {
                        writer.WriteStartElement(param.Key);  // <ParameterName>
                        if (param.Value != null)
                        {
                            var serializer = GetSerializer(param.Value.GetType());
                            serializer.WriteObjectContent(writer, param.Value);
                        }
                        else
                        {
                            // Null input
                            writer.WriteAttributeString("i","nil", "http://www.w3.org/2001/XMLSchema-instance", "true");
                        }
                        writer.WriteEndElement();            // </ParameterName>
                    }
                }

                writer.WriteEndDocument(); // </OperationName> and </MessageRoot> if present
                writer.Flush();
            }

            // TODO: Custom optimized implementation of StreamContent (like WebApi's PushStreamContent)?
            // so we don't have to have special dispose logic below
            ms.Seek(0, System.IO.SeekOrigin.Begin);
            var content = new StreamContent(ms);
            content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/msbin1");

            // Keep reference to dictionary so that we can dispose of it correctly after the request has been posted
            // otherwise there is a small risk that it will be finalized and that it might corrupt the stream
            return HttpClient.PostAsync(result.OperationName, content)
                .ContinueWith(res =>
                {
                    writer.Dispose();

                    return res;
                })
                .Unwrap();
        }
        /// <summary>
        /// Invokes a web request for the operation defined by the <see cref="WebApiDomainClientAsyncResult"/>
        /// </summary>
        /// <param name="result">The result.</param>
        /// <param name="hasSideEffects">if set to <c>true</c> then the request will always be a POST operation.</param>
        /// <param name="parameters">The parameters.</param>
        /// <param name="queryOptions">The query options.</param>
        private IAsyncResult BeginWebRequest(WebApiDomainClientAsyncResult result, bool hasSideEffects, IDictionary<string, object> parameters,
            IList<ServiceQueryPart> queryOptions)
        {
            Task<HttpResponseMessage> response = null;
            // Add parameters to query string for get methods
            if (!hasSideEffects)
            {
                response = GetAsync(result, parameters, queryOptions);
            }
            // It is a POST
            if (response == null)
            {
                response = PostAsync(result, parameters, queryOptions);
            }

            result.InnerAsyncResult = response;
            response.ContinueWith(task =>
            {
                result.Complete();
            }, TaskContinuationOptions.ExecuteSynchronously);

            return result;
        }