Skip to content

Instantly share code, notes, and snippets.

@nesterenko-kv
Forked from vanbukin/HttpCallException.cs
Created September 6, 2019 06:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nesterenko-kv/cb1d2735e843112e8eebdeded4fe7b20 to your computer and use it in GitHub Desktop.
Save nesterenko-kv/cb1d2735e843112e8eebdeded4fe7b20 to your computer and use it in GitHub Desktop.
HttpExtensinos
using System;
namespace Infrastructure.ApiClients.Http
{
public class HttpCallException : Exception
{
public HttpCallException(int? statusCode, string message) : base(message)
{
StatusCode = statusCode;
}
public int? StatusCode { get; }
}
}
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");
}
}
}
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);
}
}
}
}
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
};
}
}
<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