Files
EnvelopeGenerator/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Services/DocumentService.cs
TekH 6d0b78072e 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.
2026-10-02 13:04:29 +02:00

105 lines
4.5 KiB
C#

using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using EnvelopeGenerator.Application.Common.Dto;
namespace EnvelopeGenerator.Server.Client.Services;
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.
/// </summary>
/// <exception cref="HttpRequestException">Thrown when the API request fails.</exception>
public async Task<byte[]?> GetDocumentAsync(string envelopeKey, CancellationToken cancel = default)
{
using var http = httpClientFactory.CreateClient("EnvelopeGenerator.Server");
var response = await http.GetAsync($"/api/Document/{Uri.EscapeDataString(envelopeKey)}", cancel);
if (!response.IsSuccessStatusCode)
throw CreateHttpException("Failed to load document", response.StatusCode, response.ReasonPhrase);
var bytes = await response.Content.ReadAsByteArrayAsync(cancel);
return bytes;
}
/// <summary>
/// Fetches sender document details (including signature elements) by envelope id.
/// Uses GET /api/Document/details?EnvelopeId={envelopeId}.
/// </summary>
public async Task<DocumentDto?> GetSenderDocumentDetailsByEnvelopeIdAsync(int envelopeId, CancellationToken cancel = default)
{
using var http = httpClientFactory.CreateClient("EnvelopeGenerator.Server");
var detailsResponse = await http.GetAsync($"/api/Document/details?EnvelopeId={envelopeId}", cancel);
if (detailsResponse.StatusCode == HttpStatusCode.NotFound)
{
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 byteData = await TryGetSenderDocumentBytesByEnvelopeIdAsync(http, envelopeId, cancel);
if (byteData is null)
byteData = [];
return new DocumentDto(byteData, details);
}
/// <summary>
/// Fetches sender document bytes by envelope id.
/// Uses GET /api/Document?EnvelopeId={envelopeId}.
/// </summary>
public async Task<byte[]?> GetSenderDocumentBytesByEnvelopeIdAsync(int envelopeId, CancellationToken cancel = default)
{
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)
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);
}
}