- Added `BackToPerMethodId` constant and updated validation rules in `CloseWorkflowCommandValidator`. - Refactored `GetWorkflowsQueryHandler` for simpler `hasListingData` logic. - Replaced strongly-typed properties with `JsonElement` in `ContractsSourceBlock` and `FerdinandSourceBlock`. - Updated `WorkflowListingReadModel` to use smaller data types for efficiency. - Refactored `WorkflowRepository` to use JSON-based data retrieval and parsing. - Introduced `MetaOnlyResponse` and `WorkflowsResponse` for consistent API responses. - Updated `DocumentsController` and `WorkflowsController` to use new response types. - Added `ApiKeyAuthMiddleware` for API key validation and integrated it into the middleware pipeline. - Refactored `ExceptionHandlingMiddleware` to use `MetaOnlyResponse` for error handling. - Performed general cleanup and modernization for improved readability and maintainability.
112 lines
3.7 KiB
C#
112 lines
3.7 KiB
C#
using DigitalData.TaskFlow.Application.Common.Exceptions;
|
|
using DigitalData.TaskFlow.API.Contracts.Common;
|
|
using DigitalData.TaskFlow.Domain.Common;
|
|
using DigitalData.TaskFlow.Domain.Enums;
|
|
using FluentValidation;
|
|
using System.Text.Json;
|
|
|
|
namespace DigitalData.TaskFlow.API.Middleware;
|
|
|
|
/// <summary>
|
|
/// Handles exceptions globally and returns ticket-compatible API envelopes.
|
|
/// </summary>
|
|
public sealed class ExceptionHandlingMiddleware(RequestDelegate next, ILogger<ExceptionHandlingMiddleware> logger)
|
|
{
|
|
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web);
|
|
|
|
/// <summary>
|
|
/// Executes the middleware.
|
|
/// </summary>
|
|
/// <param name="context">HTTP context.</param>
|
|
public async Task InvokeAsync(HttpContext context)
|
|
{
|
|
try
|
|
{
|
|
await next(context);
|
|
}
|
|
catch (ApiException apiException)
|
|
{
|
|
logger.LogWarning(apiException, "API exception intercepted.");
|
|
|
|
context.Response.StatusCode = apiException.StatusCode;
|
|
context.Response.ContentType = "application/json";
|
|
|
|
var response = new MetaOnlyResponse
|
|
{
|
|
Meta =
|
|
[
|
|
new MetaEntry
|
|
{
|
|
Code = (int)apiException.MetaCode,
|
|
Message = apiException.Message
|
|
}
|
|
]
|
|
};
|
|
await context.Response.WriteAsync(JsonSerializer.Serialize(response, JsonOptions));
|
|
}
|
|
catch (ValidationException validationException)
|
|
{
|
|
logger.LogWarning(validationException, "Validation failed.");
|
|
|
|
context.Response.StatusCode = StatusCodes.Status400BadRequest;
|
|
context.Response.ContentType = "application/json";
|
|
|
|
var message = validationException.Errors.FirstOrDefault()?.ErrorMessage
|
|
?? "Ungultiger Request";
|
|
|
|
var response = new MetaOnlyResponse
|
|
{
|
|
Meta =
|
|
[
|
|
new MetaEntry
|
|
{
|
|
Code = (int)MetaCode.InvalidRequest,
|
|
Message = message
|
|
}
|
|
]
|
|
};
|
|
await context.Response.WriteAsync(JsonSerializer.Serialize(response, JsonOptions));
|
|
}
|
|
catch (NotSupportedException notSupportedException)
|
|
{
|
|
logger.LogWarning(notSupportedException, "Operation not supported yet.");
|
|
|
|
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
|
context.Response.ContentType = "application/json";
|
|
|
|
var response = new MetaOnlyResponse
|
|
{
|
|
Meta =
|
|
[
|
|
new MetaEntry
|
|
{
|
|
Code = (int)MetaCode.InternalError,
|
|
Message = notSupportedException.Message
|
|
}
|
|
]
|
|
};
|
|
await context.Response.WriteAsync(JsonSerializer.Serialize(response, JsonOptions));
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
logger.LogError(exception, "Unhandled exception.");
|
|
|
|
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
|
context.Response.ContentType = "application/json";
|
|
|
|
var response = new MetaOnlyResponse
|
|
{
|
|
Meta =
|
|
[
|
|
new MetaEntry
|
|
{
|
|
Code = (int)MetaCode.InternalError,
|
|
Message = "Interner Fehler"
|
|
}
|
|
]
|
|
};
|
|
await context.Response.WriteAsync(JsonSerializer.Serialize(response, JsonOptions));
|
|
}
|
|
}
|
|
}
|