/// <summary>
/// Extension methods for parsing API responses into OperationalResult<T>.
/// </summary>
public static class ApiResponseParser
{
/// <summary>
/// Parses the HTTP response and returns a standardized OperationalResult<T>.
/// Handles success, primitive types, and structured error responses.
/// </summary>
/// <typeparam name="T">The expected type of the result.</typeparam>
/// <param name="apiResponse">The HTTP response message.</param>
/// <returns>An OperationalResult containing the parsed result or an error.
/// </returns>
public static async Task<OperationalResult<T>> GetParsedApiResponse<T>
(this HttpResponseMessage apiResponse)
{
var responseBody = await apiResponse.Content.ReadAsStringAsync();
if (ValidHttpStatusCodes.Contains(apiResponse.StatusCode)
&& apiResponse.StatusCode != HttpStatusCode.BadRequest)
{
var type = typeof(T);
if (string.IsNullOrEmpty(responseBody))
{
return OperationalResult<T>.Successed();
}
if (type.IsPrimitive)
{
var primitiveValue = (T)Convert.ChangeType(apiResponse.Content,
typeof(T));
return OperationalResult<T>.Successed(primitiveValue);
}
var data = responseBody.JsonDeserializeObject<T>();
return OperationalResult<T>.Successed(data);
}
else
{
var apiError = responseBody.JsonDeserializeObjectTryParse<ApiError>();
if (apiError != null)
{
return OperationalResult<T>.Failed(
(ResponseStatusType)apiError.Code, apiError.Message);
}
return OperationalResult<T>.Failed(
(ResponseStatusType)apiResponse.StatusCode,
new ErrorDto($"Error: {apiResponse.StatusCode}"
, apiResponse.ReasonPhrase)
);
}
}
/// <summary>
/// A list of valid HTTP status codes considered as successful responses.
/// </summary>
public static readonly IEnumerable<HttpStatusCode> ValidHttpStatusCodes =
new List<HttpStatusCode>
{
HttpStatusCode.OK,
HttpStatusCode.Created,
HttpStatusCode.NoContent
};
}