public static async Task <T> PostMultipartAsync <T>(this HttpClient client, IContentSerializer contentSerializer,
                                                            string url, string projectAlias, object data, IDictionary <string, MultipartItem> files)
        {
            var content = await CreateContent <T>(contentSerializer, projectAlias, data, files).ConfigureAwait(false);

            var response = await client.PostAsync(url, content).ConfigureAwait(false);

            return(await contentSerializer.DeserializeAsync <T>(response.Content).ConfigureAwait(false));
        }
        public async Task <T> DeserializeAsync <T>(HttpContent content)
        {
            if (content.Headers.ContentType != null && content.Headers.ContentType.MediaType != BinarySerializer.MEDIA_TYPE)
            {
                var json = await content.ReadAsStringAsync();

                return(await _defaultSerializer.DeserializeAsync <T>(content).ConfigureAwait(false));
            }

            BinarySerializer serializer;

            if (content.Headers.ContentType == null || content.Headers.ContentType.CharSet == BinarySerializer.DefaultEncoding.WebName)
            {
                serializer = Serializer.Value;
            }
            else
            {
                var encoding = content.Headers.ContentType.CharSet == _encoding.WebName ?
                               _encoding :
                               Encoding.GetEncoding(content.Headers.ContentType.CharSet);

                serializer = new BinarySerializer(encoding);
            }

            var buffer = content.Headers?.ContentLength != null && content.Headers?.ContentLength <= MaxBufferSize?
                         _arrayPool.Rent((int)content.Headers?.ContentLength) :
                             null;

            MemoryStream stream = buffer != null ? new MemoryStream(buffer, 0, buffer.Length, true):
                                  content.Headers?.ContentLength != null ? new MemoryStream((int)content.Headers.ContentLength) :
                                  new MemoryStream();

            try
            {
                await content.CopyToAsync(stream);

                stream.Position = 0;

                return(serializer.Deserialize <T>(stream));
            }
            finally
            {
                if (buffer != null)
                {
                    _arrayPool.Return(buffer);
                }
                else
                {
                    stream?.Dispose();
                }
            }
        }
Пример #3
0
        public static string ToQueryString(this object model)
        {
            var serialized   = serializer.SerializeAsync <object>(model).Result;
            var deserialized = serializer.DeserializeAsync <Dictionary <string, string> >(serialized).Result;
            var result       = String.Empty;

            var first = true;

            foreach (var pair in deserialized)
            {
                if (first)
                {
                    first   = false;
                    result += "?";
                }
                else
                {
                    result += "&";
                }
                result += pair.Key + "=" + pair.Value;
            }
            return(result);
        }
Пример #4
0
        Func <HttpClient, CancellationToken, object[], Task <T> > BuildCancellableTaskFuncForMethod <T, TBody>(RestMethodInfo restMethod)
        {
            return(async(client, ct, paramList) =>
            {
                if (client.BaseAddress == null)
                {
                    throw new InvalidOperationException("BaseAddress must be set on the HttpClient instance");
                }

                var factory = BuildRequestFactoryForMethod(restMethod, client.BaseAddress.AbsolutePath, restMethod.CancellationToken != null);
                var rq = await factory(paramList).ConfigureAwait(false);

                HttpResponseMessage resp = null;
                HttpContent content = null;
                var disposeResponse = true;
                try
                {
                    resp = await client.SendAsync(rq, HttpCompletionOption.ResponseHeadersRead, ct).ConfigureAwait(false);

                    content = resp.Content ?? new StringContent(string.Empty);

                    if (restMethod.SerializedReturnType == typeof(HttpResponseMessage))
                    {
                        disposeResponse = false; // caller has to dispose

                        // NB: This double-casting manual-boxing hate crime is the only way to make
                        // this work without a 'class' generic constraint. It could blow up at runtime
                        // and would be A Bad Idea if we hadn't already vetted the return type.
                        return (T)(object)resp;
                    }

                    if (!resp.IsSuccessStatusCode)
                    {
                        disposeResponse = false;

                        var exception = await ApiException.Create(rq, restMethod.HttpMethod, resp, restMethod.RefitSettings).ConfigureAwait(false);

                        if (restMethod.IsApiResponse)
                        {
                            return ApiResponse.Create <T>(resp, default(T), exception);
                        }

                        throw exception;
                    }

                    var serializedReturnType = restMethod.IsApiResponse ? restMethod.SerializedGenericArgument : restMethod.SerializedReturnType;

                    if (serializedReturnType == typeof(HttpContent))
                    {
                        disposeResponse = false; // caller has to clean up the content
                        if (restMethod.IsApiResponse)
                        {
                            return ApiResponse.Create <T>(resp, content);
                        }
                        return (T)(object)content;
                    }

                    if (serializedReturnType == typeof(Stream))
                    {
                        disposeResponse = false; // caller has to dispose
                        var stream = (object)await content.ReadAsStreamAsync().ConfigureAwait(false);

                        if (restMethod.IsApiResponse)
                        {
                            return ApiResponse.Create <T>(resp, stream);
                        }
                        return (T)stream;
                    }

                    if (serializedReturnType == typeof(string))
                    {
                        using (var stream = await content.ReadAsStreamAsync().ConfigureAwait(false))
                            using (var reader = new StreamReader(stream))
                            {
                                var str = (object)await reader.ReadToEndAsync().ConfigureAwait(false);

                                if (restMethod.IsApiResponse)
                                {
                                    return ApiResponse.Create <T>(resp, str);
                                }
                                return (T)str;
                            }
                    }

                    var body = await serializer.DeserializeAsync <TBody>(content);

                    if (restMethod.IsApiResponse)
                    {
                        return ApiResponse.Create <T>(resp, body);
                    }

                    //  Unfortunate side-effect of having no 'class' or 'T : TBody' constraints.
                    //  However, we know that T must be the same as TBody because IsApiResponse != true so
                    //  this code is safe at runtime.
                    return (T)(object)body;
                }
                finally
                {
                    // Ensure we clean up the request
                    // Especially important if it has open files/streams
                    rq.Dispose();
                    if (disposeResponse)
                    {
                        resp?.Dispose();
                        content?.Dispose();
                    }
                }
            });
        }