From d7c416256c7f106018b8e216d648028c9e74e36f Mon Sep 17 00:00:00 2001 From: OlgunR Date: Tue, 16 Jun 2026 16:38:19 +0200 Subject: [PATCH] Add domain exceptions and update project structure Implemented a structured exception-handling mechanism in the domain layer with the addition of `DomainException`, `DomainValidationException`, `NotFoundException`, and `PdfProcessingException` classes. These exceptions provide specific error handling for domain logic and integrate with centralized middleware. Updated `ROADMAP.md` to mark Step 2.1 (Domain Exceptions) as completed and Step 2.2 (Value Objects) as the next task. Added timeline entries to reflect progress. Cleaned up `DocumentOperator.Domain.csproj` by removing unused folder inclusions, indicating a project structure reorganization. --- .../Common/Exceptions/DomainException.cs | 25 ++++++++++++++ .../Exceptions/DomainValidationException.cs | 28 +++++++++++++++ .../Common/Exceptions/NotFoundException.cs | 25 ++++++++++++++ .../Exceptions/PdfProcessingException.cs | 34 +++++++++++++++++++ .../DocumentOperator.Domain.csproj | 1 - ROADMAP.md | 20 ++++++----- 6 files changed, 123 insertions(+), 10 deletions(-) create mode 100644 DocumentOperator.Domain/Common/Exceptions/DomainException.cs create mode 100644 DocumentOperator.Domain/Common/Exceptions/DomainValidationException.cs create mode 100644 DocumentOperator.Domain/Common/Exceptions/NotFoundException.cs create mode 100644 DocumentOperator.Domain/Common/Exceptions/PdfProcessingException.cs diff --git a/DocumentOperator.Domain/Common/Exceptions/DomainException.cs b/DocumentOperator.Domain/Common/Exceptions/DomainException.cs new file mode 100644 index 0000000..70cdee8 --- /dev/null +++ b/DocumentOperator.Domain/Common/Exceptions/DomainException.cs @@ -0,0 +1,25 @@ +namespace DocumentOperator.Domain.Common.Exceptions; + +/// +/// Base exception for all domain-related exceptions. +/// Caught by the Exception Handling Middleware in the API layer. +/// +public abstract class DomainException : Exception +{ + /// + /// Error code for categorization and logging. + /// + public string ErrorCode { get; } + + protected DomainException(string message, string errorCode) + : base(message) + { + ErrorCode = errorCode; + } + + protected DomainException(string message, string errorCode, Exception innerException) + : base(message, innerException) + { + ErrorCode = errorCode; + } +} \ No newline at end of file diff --git a/DocumentOperator.Domain/Common/Exceptions/DomainValidationException.cs b/DocumentOperator.Domain/Common/Exceptions/DomainValidationException.cs new file mode 100644 index 0000000..fd13406 --- /dev/null +++ b/DocumentOperator.Domain/Common/Exceptions/DomainValidationException.cs @@ -0,0 +1,28 @@ +namespace DocumentOperator.Domain.Common.Exceptions; + +/// +/// Exception thrown when domain validation fails (e.g., invalid Value Objects). +/// Maps to HTTP 400 Bad Request in the API layer. +/// +public class DomainValidationException : DomainException +{ + public string PropertyName { get; } + + public DomainValidationException(string message) + : base(message, "DOMAIN_VALIDATION_ERROR") + { + PropertyName = string.Empty; + } + + public DomainValidationException(string propertyName, string message) + : base(message, "DOMAIN_VALIDATION_ERROR") + { + PropertyName = propertyName; + } + + public DomainValidationException(string message, Exception innerException) + : base(message, "DOMAIN_VALIDATION_ERROR", innerException) + { + PropertyName = string.Empty; + } +} \ No newline at end of file diff --git a/DocumentOperator.Domain/Common/Exceptions/NotFoundException.cs b/DocumentOperator.Domain/Common/Exceptions/NotFoundException.cs new file mode 100644 index 0000000..73cd81a --- /dev/null +++ b/DocumentOperator.Domain/Common/Exceptions/NotFoundException.cs @@ -0,0 +1,25 @@ +namespace DocumentOperator.Domain.Common.Exceptions; + +/// +/// Exception thrown when a requested resource is not found. +/// Maps to HTTP 404 Not Found in the API layer. +/// +public class NotFoundException : DomainException +{ + public string ResourceType { get; } + public object ResourceId { get; } + + public NotFoundException(string resourceType, object resourceId) + : base($"{resourceType} with ID '{resourceId}' was not found.", "RESOURCE_NOT_FOUND") + { + ResourceType = resourceType; + ResourceId = resourceId; + } + + public NotFoundException(string resourceType, object resourceId, string customMessage) + : base(customMessage, "RESOURCE_NOT_FOUND") + { + ResourceType = resourceType; + ResourceId = resourceId; + } +} \ No newline at end of file diff --git a/DocumentOperator.Domain/Common/Exceptions/PdfProcessingException.cs b/DocumentOperator.Domain/Common/Exceptions/PdfProcessingException.cs new file mode 100644 index 0000000..ccd73c8 --- /dev/null +++ b/DocumentOperator.Domain/Common/Exceptions/PdfProcessingException.cs @@ -0,0 +1,34 @@ +namespace DocumentOperator.Domain.Common.Exceptions; + +/// +/// Exception thrown when PDF processing operations fail. +/// Maps to HTTP 500 Internal Server Error or 422 Unprocessable Entity in the API layer. +/// +public class PdfProcessingException : DomainException +{ + public string Operation { get; } + + public PdfProcessingException(string operation, string message) + : base($"PDF processing failed during '{operation}': {message}", "PDF_PROCESSING_ERROR") + { + Operation = operation; + } + + public PdfProcessingException(string operation, string message, Exception innerException) + : base($"PDF processing failed during '{operation}': {message}", "PDF_PROCESSING_ERROR", innerException) + { + Operation = operation; + } + + public PdfProcessingException(string message) + : base(message, "PDF_PROCESSING_ERROR") + { + Operation = "Unknown"; + } + + public PdfProcessingException(string message, Exception innerException) + : base(message, "PDF_PROCESSING_ERROR", innerException) + { + Operation = "Unknown"; + } +} \ No newline at end of file diff --git a/DocumentOperator.Domain/DocumentOperator.Domain.csproj b/DocumentOperator.Domain/DocumentOperator.Domain.csproj index daf38a3..1b2cd7a 100644 --- a/DocumentOperator.Domain/DocumentOperator.Domain.csproj +++ b/DocumentOperator.Domain/DocumentOperator.Domain.csproj @@ -7,7 +7,6 @@ - diff --git a/ROADMAP.md b/ROADMAP.md index add2992..2fdc923 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -722,15 +722,15 @@ DocumentOperator.Domain/ --- -#### 🔄 Step 2.1: Domain Exceptions erstellen - **NEXT** +#### ✅ Step 2.1: Domain Exceptions erstellen - **COMPLETED** **Aufgabe:** Custom Exception-Klassen für fachliche Fehler -**Zu erstellen:** -1. [ ] `DomainException.cs` (Basis-Exception) -2. [ ] `DomainValidationException.cs` (Value Object Validierung) -3. [ ] `NotFoundException.cs` (Resource nicht gefunden) -4. [ ] `PdfProcessingException.cs` (PDF-spezifische Fehler) +**Erstellt:** +1. [x] `DomainException.cs` (Basis-Exception) +2. [x] `DomainValidationException.cs` (Value Object Validierung) +3. [x] `NotFoundException.cs` (Resource nicht gefunden) +4. [x] `PdfProcessingException.cs` (PDF-spezifische Fehler) **Wo:** `Domain/Common/Exceptions/` @@ -755,7 +755,7 @@ if (notFound) --- -#### ⏳ Step 2.2: Value Objects erstellen +#### 🔄 Step 2.2: Value Objects erstellen - **NEXT** **Aufgabe:** Typsichere, selbst-validierende Wert-Objekte @@ -1566,7 +1566,8 @@ Request mit X-API-Key → Middleware ### 🔄 In Progress - **Phase 2:** Domain Layer - - **NEXT:** Step 2.1 - Domain Exceptions erstellen + - ✅ Step 2.1 - Domain Exceptions + - **NEXT:** Step 2.2 - Value Objects ### ⏳ Pending - Phase 3-9 @@ -1629,7 +1630,8 @@ Request mit X-API-Key → Middleware | 2024-XX-XX | Phase 1 | Configuration, Serilog, Options Pattern | | 2024-XX-XX | Phase 1 | **Decision:** Exception-based statt Ardalis.Result | | 2024-XX-XX | Phase 1 | ✅ Phase 1 completed | -| 2024-XX-XX | Phase 2 | 🔄 Starting Domain Layer - Exceptions | +| 2024-XX-XX | Phase 2 | ✅ Step 2.1 completed - Domain Exceptions created | +| 2024-XX-XX | Phase 2 | 🔄 Starting Step 2.2 - Value Objects | ---