diff --git a/src/ReC.Client/ReCClientHelpers.cs b/src/ReC.Client/ReCClientHelpers.cs
index 0bf1ab3..a4f1706 100644
--- a/src/ReC.Client/ReCClientHelpers.cs
+++ b/src/ReC.Client/ReCClientHelpers.cs
@@ -5,6 +5,7 @@ using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
using System.Reflection;
+using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
@@ -73,18 +74,22 @@ namespace ReC.Client
}
///
- /// Logs the outcome of an HTTP response. Throws a when the
- /// response indicates a non-success status code; otherwise (optionally) writes an informational
- /// log entry containing the request and response details.
+ /// JSON serializer options used when deserializing API responses.
+ ///
+ public static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions
+ {
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
+ PropertyNameCaseInsensitive = true,
+ };
+
+ ///
+ /// Reads the response body and logs the outcome. Throws a when
+ /// the response indicates a non-success status code.
///
- /// The HTTP response to inspect.
- /// An optional logger used to record the outcome. May be .
- /// When , successful responses are not logged.
- /// A token to cancel the operation.
#if NETFRAMEWORK
- public static async Task HandleResponseAsync(HttpResponseMessage response, ILogger logger = null, bool logSuccess = true, CancellationToken cancel = default)
+ public static async Task HandleResponseAsync(HttpResponseMessage response, ILogger logger = null, bool logSuccess = true, CancellationToken cancel = default)
#else
- public static async Task HandleResponseAsync(HttpResponseMessage response, ILogger? logger = null, bool logSuccess = true, CancellationToken cancel = default)
+ public static async Task HandleResponseAsync(HttpResponseMessage response, ILogger? logger = null, bool logSuccess = true, CancellationToken cancel = default)
#endif
{
var request = response.RequestMessage;
@@ -92,20 +97,6 @@ namespace ReC.Client
var uri = request?.RequestUri;
var statusCode = (int)response.StatusCode;
- if (response.IsSuccessStatusCode)
- {
- if (logSuccess)
- {
- logger?.LogInformation(
- "ReC API request succeeded. {Method} {Uri} -> {StatusCode} ({ReasonPhrase})",
- method,
- uri,
- statusCode,
- response.ReasonPhrase);
- }
- return;
- }
-
#if NETFRAMEWORK
string body = null;
#else
@@ -123,15 +114,44 @@ namespace ReC.Client
}
catch
{
- // Swallow body read failures; status info is still propagated.
}
}
+ if (response.IsSuccessStatusCode)
+ {
+ if (logSuccess)
+ {
+ logger?.LogInformation(
+ "ReC API request succeeded. {Method} {Uri} -> {StatusCode} ({ReasonPhrase})",
+ method,
+ uri,
+ statusCode,
+ response.ReasonPhrase);
+ }
+
+ return body;
+ }
+
var message = $"ReC API request failed with status {statusCode} ({response.ReasonPhrase}). "
+ $"{method} {uri}"
+ (string.IsNullOrWhiteSpace(body) ? string.Empty : $": {body}");
throw new ReCApiException(message, response.StatusCode, response.ReasonPhrase, body, method, uri);
}
+
+ ///
+ /// Deserializes a JSON body string into .
+ ///
+#if NETFRAMEWORK
+ public static T Deserialize(string body)
+#else
+ public static T? Deserialize(string? body)
+#endif
+ {
+ if (string.IsNullOrWhiteSpace(body))
+ return default;
+
+ return JsonSerializer.Deserialize(body, JsonOptions);
+ }
}
}