Refactor error handling in DocumentService

Centralized `HttpRequestException` creation with a new
`CreateHttpException` method to improve code reuse and
consistency. Updated methods to handle `HttpStatusCode.NotFound`
gracefully, returning `null` where appropriate instead of
throwing exceptions. Introduced `TryGetSenderDocumentBytesByEnvelopeIdAsync`
to encapsulate fallback logic for fetching document bytes.
Removed redundant inline exception handling and standardized
error handling across methods.
This commit is contained in:
2026-10-02 13:04:29 +02:00
parent 3721ea9a1f
commit 6d0b78072e

View File

@@ -10,6 +10,15 @@ public class DocumentService(IHttpClientFactory httpClientFactory)
{
private static readonly JsonSerializerOptions _jsonOptions = new(JsonSerializerDefaults.Web);
private static HttpRequestException CreateHttpException(string messagePrefix, HttpStatusCode statusCode, string? reasonPhrase)
{
var statusCodeInt = (int)statusCode;
return new HttpRequestException(
$"{messagePrefix}. Status: {statusCodeInt} ({reasonPhrase ?? "Unknown error"})",
null,
statusCode);
}
/// <summary>
/// Fetches the PDF bytes for the given envelope key from the API.
/// Throws HttpRequestException on failure with appropriate status code.
@@ -21,14 +30,7 @@ public class DocumentService(IHttpClientFactory httpClientFactory)
var response = await http.GetAsync($"/api/Document/{Uri.EscapeDataString(envelopeKey)}", cancel);
if (!response.IsSuccessStatusCode)
{
var statusCode = (int)response.StatusCode;
var reasonPhrase = response.ReasonPhrase ?? "Unknown error";
throw new HttpRequestException(
$"Failed to load document. Status: {statusCode} ({reasonPhrase})",
null,
response.StatusCode);
}
throw CreateHttpException("Failed to load document", response.StatusCode, response.ReasonPhrase);
var bytes = await response.Content.ReadAsByteArrayAsync(cancel);
return bytes;
@@ -43,32 +45,29 @@ public class DocumentService(IHttpClientFactory httpClientFactory)
using var http = httpClientFactory.CreateClient("EnvelopeGenerator.Server");
var detailsResponse = await http.GetAsync($"/api/Document/details?EnvelopeId={envelopeId}", cancel);
if (!detailsResponse.IsSuccessStatusCode)
if (detailsResponse.StatusCode == HttpStatusCode.NotFound)
{
var statusCode = (int)detailsResponse.StatusCode;
var reasonPhrase = detailsResponse.ReasonPhrase ?? "Unknown error";
throw new HttpRequestException(
$"Failed to load sender document details. Status: {statusCode} ({reasonPhrase})",
null,
detailsResponse.StatusCode);
var fallbackBytes = await TryGetSenderDocumentBytesByEnvelopeIdAsync(http, envelopeId, cancel);
if (fallbackBytes is null)
return null;
return new DocumentDto(fallbackBytes, new DocumentDetailsDto
{
EnvelopeId = envelopeId,
AddedWhen = DateTime.UtcNow,
Elements = []
});
}
if (!detailsResponse.IsSuccessStatusCode)
throw CreateHttpException("Failed to load sender document details", detailsResponse.StatusCode, detailsResponse.ReasonPhrase);
var details = await detailsResponse.Content.ReadFromJsonAsync<DocumentDetailsDto>(_jsonOptions, cancel)
?? throw new HttpRequestException("Failed to deserialize sender document details response.");
var bytesResponse = await http.GetAsync($"/api/Document?EnvelopeId={envelopeId}", cancel);
if (!bytesResponse.IsSuccessStatusCode)
{
var statusCode = (int)bytesResponse.StatusCode;
var reasonPhrase = bytesResponse.ReasonPhrase ?? "Unknown error";
throw new HttpRequestException(
$"Failed to load sender document bytes. Status: {statusCode} ({reasonPhrase})",
null,
bytesResponse.StatusCode);
}
var byteData = await bytesResponse.Content.ReadAsByteArrayAsync(cancel);
var byteData = await TryGetSenderDocumentBytesByEnvelopeIdAsync(http, envelopeId, cancel);
if (byteData is null)
byteData = [];
return new DocumentDto(byteData, details);
}
@@ -82,16 +81,24 @@ public class DocumentService(IHttpClientFactory httpClientFactory)
using var http = httpClientFactory.CreateClient("EnvelopeGenerator.Server");
var response = await http.GetAsync($"/api/Document?EnvelopeId={envelopeId}", cancel);
if (response.StatusCode == HttpStatusCode.NotFound)
return null;
if (!response.IsSuccessStatusCode)
{
var statusCode = (int)response.StatusCode;
var reasonPhrase = response.ReasonPhrase ?? "Unknown error";
throw new HttpRequestException(
$"Failed to load sender document bytes. Status: {statusCode} ({reasonPhrase})",
null,
response.StatusCode);
}
throw CreateHttpException("Failed to load sender document bytes", response.StatusCode, response.ReasonPhrase);
return await response.Content.ReadAsByteArrayAsync(cancel);
}
private static async Task<byte[]?> TryGetSenderDocumentBytesByEnvelopeIdAsync(HttpClient http, int envelopeId, CancellationToken cancel)
{
var bytesResponse = await http.GetAsync($"/api/Document?EnvelopeId={envelopeId}", cancel);
if (bytesResponse.StatusCode == HttpStatusCode.NotFound)
return null;
if (!bytesResponse.IsSuccessStatusCode)
throw CreateHttpException("Failed to load sender document bytes", bytesResponse.StatusCode, bytesResponse.ReasonPhrase);
return await bytesResponse.Content.ReadAsByteArrayAsync(cancel);
}
}