# 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` that carries data along with the status: ```csharp // Success with data Result customerResult = Result.AsSuccess(customer); // Error with no data Result errorResult = Result.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 : Response { [DataMember] public List 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 to Response Response response = Response.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`, the data is added to the `Response.Result` collection ## Usage Examples ### Business Logic Layer (BL) ```csharp public Result GetCustomerById(int customerId) { try { var customer = this._repository.GetCustomerById(customerId); if (customer == null) return Result.AsError("Customer not found"); var dto = this.ConvertToDTO(customer); return Result.AsSuccess(dto); } catch (Exception ex) { return Result.FromException(ex); } } ``` ### Web Service Layer ```csharp public Response GetCustomerById(int customerId) { var result = this._customerBL.GetCustomerById(customerId); return Response.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.