Files
DocumentService/DocumentOperator.Application/ValidatePdf/Queries/ValidatePdfQuery.cs
TekH d6e3a5fda1 refactor: Restructure Application layer with vertical slices and AutoMapper
Vertical slice architecture:

  - Move Features/Documents/{UseCase}/ to {UseCase}/Queries/

  - Query + Handler in SAME file (co-located)

  - Validator in separate file (single responsibility)

New structure:

  - ValidatePdf/Queries/ValidatePdfQuery.cs (Query + Handler)

  - ValidatePdf/Queries/ValidatePdfQueryValidator.cs

  - SwissQrCode/Queries/ExtractSwissQrCodeQuery.cs (Query + Handler)

  - SwissQrCode/Queries/ExtractSwissQrCodeQueryValidator.cs

AutoMapper integration:

  - Add Common/Mapping/MappingProfile.cs

  - Map PdfMetadata -> PdfValidationResult (domain -> DTO)

  - Map SwissQrCodeData -> SwissQrCodeExtractionResult (domain -> DTO)

  - Controllers now thin: pass request to MediatR, AutoMapper handles mapping

DTO improvements:

  - Rename: ValidatePdfResponse -> PdfValidationResult (business-friendly)

  - Rename: ExtractSwissQrCodeResponse -> SwissQrCodeExtractionResult

  - Support BOTH byte[] and Base64Pdf string (XOR validation)

  - Use modern C# 12 collection expressions

Code quality:

  - Use PascalCase for primary constructor parameters

  - Fix LoggingBehavior logging format

Deleted old structure:

  - Features/Documents/ValidatePdf/ (old horizontal structure)

  - Features/Documents/ExtractSwissQrCode/ (old horizontal structure)

  - Common/DTOs/{Request|Response} (replaced with {Result})

Result: Vertical slices, AutoMapper v16.2.0, thin controllers
2026-07-07 19:01:05 +02:00

46 lines
1.5 KiB
C#

using AutoMapper;
using DocumentOperator.Application.Common.DTOs;
using DocumentOperator.Application.Common.Interfaces;
using MediatR;
namespace DocumentOperator.Application.ValidatePdf.Queries;
/// <summary>
/// Query for PDF validation (supports both byte array and Base64 input)
/// </summary>
public record ValidatePdfQuery : IRequest<PdfValidationResult>
{
/// <summary>
/// PDF as byte array (direct upload)
/// </summary>
public byte[]? PdfBytes { get; init; }
/// <summary>
/// PDF as Base64 string (API clients)
/// </summary>
public string? Base64Pdf { get; init; }
}
/// <summary>
/// Handler for ValidatePdfQuery
/// Orchestrates PDF validation using IPdfProcessor and AutoMapper
/// </summary>
public class ValidatePdfQueryHandler(IPdfProcessor PdfProcessor, IMapper Mapper)
: IRequestHandler<ValidatePdfQuery, PdfValidationResult>
{
/// <summary>
/// Validates PDF and returns metadata
/// </summary>
public async Task<PdfValidationResult> Handle(ValidatePdfQuery request, CancellationToken cancellationToken)
{
// Use byte[] if available, otherwise convert Base64
byte[] pdfBytes = request.PdfBytes ?? Convert.FromBase64String(request.Base64Pdf!);
// Call DevExpress service (can throw PdfProcessingException)
var metadata = await PdfProcessor.ValidateAsync(pdfBytes);
// Map domain entity to DTO using AutoMapper
return Mapper.Map<PdfValidationResult>(metadata);
}
}