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