Last active
September 6, 2019 06:50
-
-
Save vanbukin/e9d26bc347907dbe6547bce87a90abad to your computer and use it in GitHub Desktop.
HttpExtensinos
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace Infrastructure.ApiClients.Http | |
{ | |
public class HttpCallException : Exception | |
{ | |
public HttpCallException(int? statusCode, string message) : base(message) | |
{ | |
StatusCode = statusCode; | |
} | |
public int? StatusCode { get; } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Infrastructure.ApiClients.Http | |
{ | |
public class HttpCallResult | |
{ | |
public HttpCallResult(bool isSuccessful, int? statusCode) | |
{ | |
IsSuccessful = isSuccessful; | |
StatusCode = statusCode; | |
} | |
public bool IsSuccessful { get; } | |
public int? StatusCode { get; } | |
public virtual void ThrowIfError(string errorMessage = "HTTP API call wasn't successful") | |
{ | |
if (!IsSuccessful) | |
throw new HttpCallException(StatusCode, errorMessage); | |
} | |
} | |
public class HttpCallResult<TResult> : HttpCallResult | |
{ | |
public HttpCallResult(bool isSuccessful, int? statusCode, TResult result) : base(isSuccessful, statusCode) | |
{ | |
Result = result; | |
} | |
public TResult Result { get; } | |
public override void ThrowIfError(string errorMessage = "HTTP API call wasn't successful") | |
{ | |
if (!IsSuccessful) | |
throw new HttpCallException(StatusCode, errorMessage); | |
if (Result is null) | |
throw new HttpCallException(StatusCode, "Returned result is null or empty"); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Net.Http; | |
using System.Net.Http.Headers; | |
using System.Text.Json; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace Infrastructure.ApiClients.Http | |
{ | |
public static class HttpClientExtensions | |
{ | |
public static async Task<HttpCallResult<TResponseModel>> CallApiAsync<TRequestModel, TResponseModel>( | |
this HttpClient httpClient, | |
string requestUri, | |
HttpMethod method, | |
TRequestModel requestModel, | |
bool rethrowInnerExceptions = false, | |
CancellationToken cancellationToken = default) | |
{ | |
return await httpClient.CallApiAsync<TRequestModel, TResponseModel>( | |
requestUri, | |
method, | |
requestModel, | |
HttpJsonSerializerOptions.Default, | |
HttpJsonSerializerOptions.Default, | |
rethrowInnerExceptions, | |
cancellationToken); | |
} | |
public static async Task<HttpCallResult<TResponseModel>> CallApiAsync<TRequestModel, TResponseModel>( | |
this HttpClient httpClient, | |
string requestUri, | |
HttpMethod method, | |
TRequestModel requestModel, | |
JsonSerializerOptions? requestSerializerOptions, | |
JsonSerializerOptions? responseSerializerOptions, | |
bool rethrowInnerExceptions, | |
CancellationToken cancellationToken = default) | |
{ | |
int? statusCode = null; | |
try | |
{ | |
cancellationToken.ThrowIfCancellationRequested(); | |
using var requestStream = new MemoryStream(); | |
await JsonSerializer.SerializeAsync( | |
requestStream, | |
requestModel, | |
requestSerializerOptions, | |
cancellationToken); | |
requestStream.Seek(0L, SeekOrigin.Begin); | |
using var request = new HttpRequestMessage(method, requestUri) | |
{ | |
Content = new StreamContent(requestStream) | |
}; | |
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); | |
using var response = await httpClient.SendAsync( | |
request, | |
HttpCompletionOption.ResponseHeadersRead, | |
cancellationToken); | |
statusCode = (int) response.StatusCode; | |
var successfulResponse = response.EnsureSuccessStatusCode(); | |
using var responseStream = await successfulResponse.Content.ReadAsStreamAsync(); | |
var responseObject = await JsonSerializer.DeserializeAsync<TResponseModel>( | |
responseStream, | |
responseSerializerOptions, | |
cancellationToken); | |
return new HttpCallResult<TResponseModel>(true, statusCode, responseObject); | |
} | |
catch (Exception) | |
{ | |
if (rethrowInnerExceptions) | |
throw; | |
#nullable disable | |
return new HttpCallResult<TResponseModel>(false, statusCode, default); | |
#nullable restore | |
} | |
} | |
public static async Task<HttpCallResult<TResponseModel>> CallApiAsync<TResponseModel>( | |
this HttpClient httpClient, | |
string requestUri, | |
HttpMethod method, | |
bool rethrowInnerExceptions = false, | |
CancellationToken cancellationToken = default) | |
{ | |
return await httpClient.CallApiAsync<TResponseModel>( | |
requestUri, | |
method, | |
HttpJsonSerializerOptions.Default, | |
rethrowInnerExceptions, | |
cancellationToken); | |
} | |
public static async Task<HttpCallResult<TResponseModel>> CallApiAsync<TResponseModel>( | |
this HttpClient httpClient, | |
string requestUri, | |
HttpMethod method, | |
JsonSerializerOptions? responseSerializerOptions = null, | |
bool rethrowInnerExceptions = false, | |
CancellationToken cancellationToken = default) | |
{ | |
int? statusCode = null; | |
try | |
{ | |
cancellationToken.ThrowIfCancellationRequested(); | |
using var request = new HttpRequestMessage(method, requestUri); | |
using var response = await httpClient.SendAsync( | |
request, | |
HttpCompletionOption.ResponseHeadersRead, | |
cancellationToken); | |
statusCode = (int) response.StatusCode; | |
var successfulResponse = response.EnsureSuccessStatusCode(); | |
var responseStream = await successfulResponse.Content.ReadAsStreamAsync(); | |
var responseObject = await JsonSerializer.DeserializeAsync<TResponseModel>( | |
responseStream, | |
responseSerializerOptions, | |
cancellationToken); | |
return new HttpCallResult<TResponseModel>(true, statusCode, responseObject); | |
} | |
catch (Exception) | |
{ | |
if (rethrowInnerExceptions) | |
throw; | |
#nullable disable | |
return new HttpCallResult<TResponseModel>(false, statusCode, default); | |
#nullable restore | |
} | |
} | |
public static async Task<HttpCallResult> CallApiAsync<TRequestModel>( | |
this HttpClient httpClient, | |
string requestUri, | |
HttpMethod method, | |
TRequestModel requestModel, | |
bool rethrowInnerExceptions = false, | |
CancellationToken cancellationToken = default) | |
{ | |
return await httpClient.CallApiAsync( | |
requestUri, | |
method, | |
requestModel, | |
HttpJsonSerializerOptions.Default, | |
rethrowInnerExceptions, | |
cancellationToken); | |
} | |
public static async Task<HttpCallResult> CallApiAsync<TRequestModel>( | |
this HttpClient httpClient, | |
string requestUri, | |
HttpMethod method, | |
TRequestModel requestModel, | |
JsonSerializerOptions? requestSerializerOptions = null, | |
bool rethrowInnerExceptions = false, | |
CancellationToken cancellationToken = default) | |
{ | |
int? statusCode = null; | |
try | |
{ | |
cancellationToken.ThrowIfCancellationRequested(); | |
using var requestStream = new MemoryStream(); | |
await JsonSerializer.SerializeAsync( | |
requestStream, | |
requestModel, | |
requestSerializerOptions, | |
cancellationToken); | |
requestStream.Seek(0L, SeekOrigin.Begin); | |
using var request = new HttpRequestMessage(method, requestUri) | |
{ | |
Content = new StreamContent(requestStream) | |
}; | |
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); | |
using var response = await httpClient.SendAsync( | |
request, | |
HttpCompletionOption.ResponseContentRead, | |
cancellationToken); | |
statusCode = (int) response.StatusCode; | |
response.EnsureSuccessStatusCode(); | |
return new HttpCallResult(true, statusCode); | |
} | |
catch (Exception) | |
{ | |
if (rethrowInnerExceptions) | |
throw; | |
return new HttpCallResult(false, statusCode); | |
} | |
} | |
public static async Task<HttpCallResult> CallApiAsync( | |
this HttpClient httpClient, | |
string requestUri, | |
HttpMethod method, | |
bool rethrowInnerExceptions = false, | |
CancellationToken cancellationToken = default) | |
{ | |
int? statusCode = null; | |
try | |
{ | |
cancellationToken.ThrowIfCancellationRequested(); | |
using var request = new HttpRequestMessage(method, requestUri); | |
using var response = await httpClient.SendAsync( | |
request, | |
HttpCompletionOption.ResponseContentRead, | |
cancellationToken); | |
statusCode = (int) response.StatusCode; | |
response.EnsureSuccessStatusCode(); | |
return new HttpCallResult(true, statusCode); | |
} | |
catch (Exception) | |
{ | |
if (rethrowInnerExceptions) | |
throw; | |
return new HttpCallResult(false, statusCode); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Text.Json; | |
namespace Infrastructure.ApiClients.Http | |
{ | |
public static class HttpJsonSerializerOptions | |
{ | |
public static JsonSerializerOptions Default { get; } = new JsonSerializerOptions | |
{ | |
MaxDepth = 32, | |
PropertyNameCaseInsensitive = true, | |
PropertyNamingPolicy = JsonNamingPolicy.CamelCase | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<TargetFramework>netstandard2.0</TargetFramework> | |
<LangVersion>8</LangVersion> | |
<Nullable>enable</Nullable> | |
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="System.Text.Json" Version="4.6.0-preview8.19405.3" /> | |
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.3" /> | |
</ItemGroup> | |
</Project> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment