Files
Christoph Schwörer f045b99a25 Codebasis als Dateien ins Arbeitsrepo statt als Gitlink
QuellCode/CentronERP war nur als Gitlink (Submodul-Referenz auf 79c1142)
getrackt, ohne .gitmodules und ohne erreichbares Remote. Der
Untersuchungsgegenstand der Versuchsreihe war damit nicht reproduzierbar
gesichert: Ein Klon haette ein leeres Verzeichnis erhalten, und die Belege
der 3.287 Anforderungen waeren nicht ueberpruefbar gewesen.

Umstellung:
- Historie nach c:\DEV\CentronERP_git_snapshot_79c1142 ausgelagert
  (vollstaendig lesbar, enthaelt 79c1142 und Vorgaenger 89ccfd6)
- Gitlink aus dem Index entfernt
- Dateiinhalt aufgenommen: 24.557 Dateien, rund 333 MB

Die verschachtelte .gitignore der Codebasis gilt weiter, Build-Artefakte
bleiben ausgeschlossen. Details in Versuche/Versuch_01/_Codebasis-Nachweis.md
2026-08-26 07:43:51 +02:00

225 lines
6.3 KiB
Markdown

# Results and Responses in c-entron.NET
This document explains the `Result` and `Response` classes in c-entron.NET, their purpose, and how they interact across the system layers. These classes form a critical part of the error handling and communication pattern throughout the application.
## Overview
In c-entron.NET, we use a standardized approach for operation results and API responses:
1. **`Result`** - Internal class used within the business logic layer to indicate operation success/failure
2. **`Response`** - Web service API class that translates `Result` objects to client-friendly responses
This pattern provides:
- Consistent error handling across all application layers
- Type-safe return values with status information
- Clean separation between internal logic and API responses
- Standardized way to include error messages and codes
## Result Class
### Location
`src/backend/Centron.Interfaces/Results/Result.cs`
### Purpose
The `Result` class represents the outcome of an operation in the business logic layer. It includes not just the success/failure status, but also contextual information like error messages and exception details.
### Structure
```csharp
public class Result
{
public string Message { get; protected set; }
public int? MessageCode { get; protected set; }
public Exception Error { get; protected set; }
public ResultStatus Status { get; protected set; }
// Factory methods and constructors...
}
```
### Status Values
The `Result` object can have one of the following statuses:
- **Success** - The operation completed successfully
- **Error** - The operation failed due to an error
- **Warning** - The operation completed but with warnings
### Factory Methods
The `Result` class uses factory methods (instead of constructors) for creating result objects:
```csharp
// Success results
Result.AsSuccess();
Result.AsSuccess("Operation completed successfully");
// Error results
Result.AsError("The operation failed", messageCode: 100);
Result.AsError("Invalid input", error: exception);
// Warning results
Result.AsWarning("Some fields could not be processed");
// From exceptions
Result.FromException("Failed to process request", exception);
Result.FromException(exception);
```
### Generic Version
There is also a generic version `Result<T>` that carries data along with the status:
```csharp
// Success with data
Result<Customer> customerResult = Result<Customer>.AsSuccess(customer);
// Error with no data
Result<Customer> errorResult = Result<Customer>.AsError("Customer not found");
```
## Response Class
### Location
`src/webservice/Centron.WebServices.Core/Messages/Response.cs`
### Purpose
The `Response` class serves as the API response format returned by web services to clients. It translates the internal `Result` objects into standardized API responses.
### Structure
```csharp
[DataContract]
public class Response
{
[DataMember]
public StatusCode Status { get; set; }
[DataMember]
public string Message { get; set; }
[DataMember]
public int MessageCode { get; set; }
// Factory methods...
}
[DataContract]
public class Response<T> : Response
{
[DataMember]
public List<T> Result { get; set; }
// Additional factory methods...
}
```
### Status Values
The `Response` object can have one of the following statuses:
- **Success** - The operation completed successfully
- **Failed** - The operation failed due to an error
Note that unlike `Result`, `Response` maps both `ResultStatus.Success` and `ResultStatus.Warning` to `StatusCode.Success`.
## Interaction Between Result and Response
The key interaction occurs through the `FromBLResult` methods in the `Response` class:
```csharp
// Converting a Result to Response
Response response = Response.FromResult(result);
// Converting a Result<T> to Response<T>
Response<Customer> response = Response<Customer>.FromBLResult(customerResult);
```
### Mapping Logic
1. `Result.Status` is mapped to `Response.Status`:
- `ResultStatus.Success` → `StatusCode.Success`
- `ResultStatus.Warning` → `StatusCode.Success` (warnings are treated as success at API level)
- `ResultStatus.Error` → `StatusCode.Failed`
2. `Result.Message` is directly copied to `Response.Message`
3. `Result.MessageCode` is copied to `Response.MessageCode` (with a default if not provided)
4. For `Result<T>`, the data is added to the `Response<T>.Result` collection
## Usage Examples
### Business Logic Layer (BL)
```csharp
public Result<CustomerDTO> GetCustomerById(int customerId)
{
try
{
var customer = this._repository.GetCustomerById(customerId);
if (customer == null)
return Result<CustomerDTO>.AsError("Customer not found");
var dto = this.ConvertToDTO(customer);
return Result<CustomerDTO>.AsSuccess(dto);
}
catch (Exception ex)
{
return Result<CustomerDTO>.FromException(ex);
}
}
```
### Web Service Layer
```csharp
public Response<CustomerDTO> GetCustomerById(int customerId)
{
var result = this._customerBL.GetCustomerById(customerId);
return Response<CustomerDTO>.FromBLResult(result);
}
```
## Best Practices
1. **Always use factory methods** instead of constructors for creating `Result` objects
```csharp
// Good
return Result.AsSuccess("Operation succeeded");
// Avoid
return new Result(ResultStatus.Success, "Operation succeeded");
```
2. **Include meaningful error messages** to help diagnose issues
```csharp
// Good
return Result.AsError($"Customer with ID {id} not found");
// Avoid
return Result.AsError("Not found");
```
3. **Propagate exceptions appropriately** using `FromException`
```csharp
try
{
// Operation code
}
catch (Exception ex)
{
return Result.FromException("Failed to complete operation", ex);
}
```
4. **Use `ThrowIfError` extension method** when chaining operations
```csharp
var result = await someOperation().ThrowIfError();
```
5. **Convert between `Result` and `Response` only at service boundaries** to maintain clean separation of concerns
## Conclusion
The `Result` and `Response` classes provide a robust pattern for error handling and operation results throughout the c-entron.NET application. Understanding how they work together is essential for maintaining consistency in API responses and proper error handling across all application layers.