Refactor envelope receiver auth flow and state handling

- Introduce IReceiverAuthService and ReceiverAuthService for all envelope receiver authentication and status API calls
- Add ReceiverAuthModel as a client-side DTO for API responses
- Refactor EnvelopeState to store all relevant fields and update via ApplyApiResponse
- Overhaul EnvelopePage.razor to use new service and state, with improved status handling and UI
- Enhance ApiResponse and ApiServiceBase to support structured error deserialization
- Register IReceiverAuthService in DI container
This commit is contained in:
OlgunR
2026-03-23 15:57:20 +01:00
parent 4aa889f178
commit 93488ba83e
8 changed files with 320 additions and 59 deletions

View File

@@ -37,7 +37,13 @@ public abstract class ApiServiceBase
var errorBody = await response.Content.ReadAsStringAsync(ct);
Logger.LogWarning("GET {Endpoint} failed: {Status} - {Body}",
endpoint, (int)response.StatusCode, errorBody);
return ApiResponse<T>.Failure((int)response.StatusCode, errorBody);
// Versuche den Body trotzdem zu deserialisieren —
// die API gibt bei 401/404 oft strukturierte JSON-Antworten zurück
// (z.B. ReceiverAuthResponse mit ErrorMessage + Status)
var errorData = await TryDeserializeAsync<T>(response, ct);
return ApiResponse<T>.Failure((int)response.StatusCode, errorBody, errorData);
}
var data = await response.Content.ReadFromJsonAsync<T>(cancellationToken: ct);
@@ -70,7 +76,10 @@ public abstract class ApiServiceBase
var errorBody = await response.Content.ReadAsStringAsync(ct);
Logger.LogWarning("POST {Endpoint} failed: {Status} - {Body}",
endpoint, (int)response.StatusCode, errorBody);
return ApiResponse<TResponse>.Failure((int)response.StatusCode, errorBody);
var errorData = await TryDeserializeAsync<TResponse>(response, ct);
return ApiResponse<TResponse>.Failure((int)response.StatusCode, errorBody, errorData);
}
var data = await response.Content.ReadFromJsonAsync<TResponse>(cancellationToken: ct);
@@ -107,4 +116,26 @@ public abstract class ApiServiceBase
return ApiResponse.Failure(0, "Verbindung zum Server fehlgeschlagen.");
}
}
/// <summary>
/// Versucht den Response-Body als JSON zu deserialisieren.
/// Gibt null zurück wenn es nicht klappt (z.B. bei HTML-Fehlerseiten).
/// </summary>
private static async Task<T?> TryDeserializeAsync<T>(HttpResponseMessage response, CancellationToken ct)
{
try
{
// Nur versuchen wenn der Content-Type JSON ist
if (response.Content.Headers.ContentType?.MediaType == "application/json")
{
return await response.Content.ReadFromJsonAsync<T>(cancellationToken: ct);
}
}
catch
{
// Ignorieren — der Body war kein valides JSON
}
return default;
}
}