Refactor error handling in DocumentService and consumers

Refactored `DocumentService.GetDocumentAsync` to throw
`HttpRequestException` on failure instead of returning a tuple.
Updated all consumers to handle exceptions, improving error
handling consistency across the application.

Enhanced error messages for better user feedback and added
logging for improved traceability. Updated `EnvelopeReceiverPage`,
`EnvelopeReceiverPage_DxReportViewer`, and `ReportViewer` to
use the new exception-based API and handle errors gracefully.

This change simplifies the API, improves maintainability, and
makes the application more robust and user-friendly.
This commit is contained in:
2026-06-11 13:33:15 +02:00
parent ecb7f45f14
commit cf16312394
4 changed files with 35 additions and 14 deletions

View File

@@ -563,13 +563,13 @@ const int MaxThumbnailWidth = 400;
} }
try { try {
var (pdfBytes, statusCode) = await DocumentService.GetDocumentAsync(EnvelopeKey); var pdfBytes = await DocumentService.GetDocumentAsync(EnvelopeKey);
if (pdfBytes is { Length: > 0 }) { if (pdfBytes is { Length: > 0 }) {
var base64 = Convert.ToBase64String(pdfBytes); var base64 = Convert.ToBase64String(pdfBytes);
_pdfDataUrl = $"data:application/pdf;base64,{base64}"; _pdfDataUrl = $"data:application/pdf;base64,{base64}";
} else { } else {
_errorMessage = $"Dokument konnte nicht geladen werden. HTTP Status: {statusCode}"; _errorMessage = "Dokument konnte nicht geladen werden: Keine Daten empfangen.";
} }
var signatures = await SignatureService.GetAsync(EnvelopeKey); var signatures = await SignatureService.GetAsync(EnvelopeKey);
@@ -608,8 +608,12 @@ const int MaxThumbnailWidth = 400;
_popupValidationMessage = null; _popupValidationMessage = null;
} }
} catch (HttpRequestException ex) {
_errorMessage = $"Dokument konnte nicht geladen werden: {ex.Message}";
logger.LogError(ex, "Failed to load document for envelope {EnvelopeKey}", EnvelopeKey);
} catch (Exception ex) { } catch (Exception ex) {
_errorMessage = $"Fehler: {ex.Message}"; _errorMessage = $"Fehler: {ex.Message}";
logger.LogError(ex, "Unexpected error during initialization for envelope {EnvelopeKey}", EnvelopeKey);
} }
_isLoading = false; _isLoading = false;

View File

@@ -25,11 +25,15 @@
protected override async Task OnInitializedAsync() { protected override async Task OnInitializedAsync() {
if (!AppOptions.Value.UsePredefinedReports) { if (!AppOptions.Value.UsePredefinedReports) {
var (pdfBytes, _) = await DocumentService.GetDocumentAsync(EnvelopeKey); try {
var pdfBytes = await DocumentService.GetDocumentAsync(EnvelopeKey);
if (pdfBytes is { Length: > 0 }) if (pdfBytes is { Length: > 0 })
BasePdfBytes = pdfBytes; BasePdfBytes = pdfBytes;
else else
throw new InvalidOperationException($"No PDF bytes found for EnvelopeKey: {EnvelopeKey}"); throw new InvalidOperationException($"No PDF bytes found for EnvelopeKey: {EnvelopeKey}");
} catch (HttpRequestException ex) {
throw new InvalidOperationException($"Failed to load document for EnvelopeKey: {EnvelopeKey}", ex);
}
} }
Report = CreateReport(); Report = CreateReport();

View File

@@ -346,9 +346,14 @@ Shown="OnPopupShownAsync">
_envelopeReceiver = await EnvelopeReceiverService.GetAsync(EnvelopeKey ?? "fake"); _envelopeReceiver = await EnvelopeReceiverService.GetAsync(EnvelopeKey ?? "fake");
if (!AppOptions.Value.UsePredefinedReports && !string.IsNullOrWhiteSpace(EnvelopeKey)) { if (!AppOptions.Value.UsePredefinedReports && !string.IsNullOrWhiteSpace(EnvelopeKey)) {
var (pdfBytes, _) = await DocumentService.GetDocumentAsync(EnvelopeKey); try {
var pdfBytes = await DocumentService.GetDocumentAsync(EnvelopeKey);
if (pdfBytes is { Length: > 0 }) if (pdfBytes is { Length: > 0 })
_basePdfBytes = pdfBytes; _basePdfBytes = pdfBytes;
} catch (HttpRequestException ex) {
// Log error but continue - will use predefined report instead
Console.WriteLine($"Failed to load document: {ex.Message}");
}
} }
var initialReport = BuildFreshBaseReport(); var initialReport = BuildFreshBaseReport();

View File

@@ -11,17 +11,25 @@ public class DocumentService(HttpClient http, IOptions<ApiOptions> apiOptions)
/// <summary> /// <summary>
/// Fetches the PDF bytes for the given envelope key from the API. /// Fetches the PDF bytes for the given envelope key from the API.
/// Returns null bytes with the HTTP status code on failure. /// Throws HttpRequestException on failure with appropriate status code.
/// </summary> /// </summary>
public async Task<(byte[]? Bytes, HttpStatusCode StatusCode)> GetDocumentAsync(string envelopeKey, CancellationToken cancel = default) /// <exception cref="HttpRequestException">Thrown when the API request fails.</exception>
public async Task<byte[]?> GetDocumentAsync(string envelopeKey, CancellationToken cancel = default)
{ {
var response = await http.GetAsync($"{_api.BaseUrl}/api/Document/{Uri.EscapeDataString(envelopeKey)}", cancel); var response = await http.GetAsync($"{_api.BaseUrl}/api/Document/{Uri.EscapeDataString(envelopeKey)}", cancel);
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
return (null, response.StatusCode); {
var statusCode = (int)response.StatusCode;
var reasonPhrase = response.ReasonPhrase ?? "Unknown error";
throw new HttpRequestException(
$"Failed to load document. Status: {statusCode} ({reasonPhrase})",
null,
response.StatusCode);
}
var bytes = await response.Content.ReadAsByteArrayAsync(cancel); var bytes = await response.Content.ReadAsByteArrayAsync(cancel);
return (bytes, response.StatusCode); return bytes;
} }
} }