Zentient Results Api Reference Core Components - ulfbou/Zentient.Results GitHub Wiki

⚙️ Core Components


The core components of Zentient.Results provide the foundational elements for defining, categorizing, and managing operation outcomes and errors. They enable structured error reporting and clear status indications.

ErrorInfo Struct

The ErrorInfo struct is an immutable value type that encapsulates detailed, structured information about a specific error or validation problem. It serves as the primary mechanism for reporting why an operation failed, providing context that goes beyond a simple string message.

namespace Zentient.Results
{
    /// <summary>
    /// Represents detailed, structured information about an error or validation problem.
    /// </summary>
    public readonly struct ErrorInfo : IEquatable<ErrorInfo>
    {
        /// <summary>
        /// Gets the category of the error, providing a broad classification.
        /// </summary>
        public ErrorCategory Category { get; }

        /// <summary>
        /// Gets a unique code or identifier for this specific error type.
        /// </summary>
        public string Code { get; }

        /// <summary>
        /// Gets a human-readable message describing the error.
        /// </summary>
        public string Message { get; }

        /// <summary>
        /// Gets an optional list of associated parameters or contextual data relevant to the error.
        /// </summary>
        public IReadOnlyDictionary<string, object> Parameters { get; }

        /// <summary>
        /// Initializes a new instance of the <see cref="ErrorInfo"/> struct.
        /// </summary>
        /// <param name="category">The category of the error.</param>
        /// <param name="code">A unique code or identifier for this error type.</param>
        /// <param name="message">A human-readable message describing the error.</param>
        /// <param name="parameters">Optional dictionary of parameters or contextual data.</param>
        public ErrorInfo(
            ErrorCategory category,
            string code,
            string message,
            IDictionary<string, object>? parameters = null);

        /// <summary>
        /// Returns a string representation of the <see cref="ErrorInfo"/>.
        /// </summary>
        /// <returns>A string in the format "Code: Message (Category)".</returns>
        public override string ToString();

        // IEquatable implementation (Equals, GetHashCode)
        // Comparison operators (==, !=)
    }
}

Properties

  • Category: ErrorCategory

    • Description: A broad classification of the error, defined by the ErrorCategory enum. This helps in grouping and handling errors based on their general nature (e.g., Validation, BusinessLogic, NotFound).
    • Usage: Useful for high-level error filtering or routing.
    • See Also: ErrorCategory Enum
    • Example: if (error.Category == ErrorCategory.Validation) { /* ... */ }
  • Code: string

    • Description: A unique, machine-readable identifier for the specific type of error. This should be consistent across your application and potentially between services.
    • Usage: For programmatic error identification and specific error handling logic.
    • Example: if (error.Code == "UserAlreadyExists") { /* ... */ }
  • Message: string

    • Description: A human-readable description of the error. This message is suitable for display to end-users or for logging.
    • Usage: Displaying error messages in UI, logging.
    • Example: Console.WriteLine(error.Message);
  • Parameters: IReadOnlyDictionary<string, object>

    • Description: An optional dictionary containing additional contextual data relevant to the error. This allows you to attach specific details (e.g., invalid field names, conflicting IDs) without bloating the main ErrorInfo properties.
    • Usage: Providing detailed context for debugging or specific error handling.
    • Example: if (error.Parameters.TryGetValue("FieldName", out var fieldName)) { /* ... */ }

Constructor

  • ErrorInfo(ErrorCategory category, string code, string message, IDictionary<string, object>? parameters = null)
    • Description: Initializes a new instance of ErrorInfo.
    • Parameters:
      • category: The error's broad classification.
      • code: The unique identifier for the error.
      • message: The human-readable description.
      • parameters: (Optional) A dictionary of additional contextual data.

Methods

  • ToString(): string
    • Description: Provides a concise string representation of the ErrorInfo in the format "Code: Message (Category)".
    • Usage: For quick logging or debugging output.

Usage Example

using Zentient.Results;
using System.Collections.Generic;

// Creating a validation error
var validationError = new ErrorInfo(
    ErrorCategory.Validation,
    "InvalidInput",
    "The provided input is not in the correct format.",
    new Dictionary<string, object> { { "InputType", "Email" }, { "ValueProvided", "notAnEmail" } }
);

Console.WriteLine($"Error: {validationError.Code} - {validationError.Message} ({validationError.Category})");
Console.WriteLine($"Parameter: InputType = {validationError.Parameters["InputType"]}");

// Creating a business logic error
var businessError = new ErrorInfo(
    ErrorCategory.BusinessLogic,
    "InsufficientFunds",
    "Account balance is too low for this transaction."
);

Console.WriteLine($"Error: {businessError.Code} - {businessError.Message}");

ErrorCategory Enum

The ErrorCategory enum provides a standard set of broad classifications for errors. Using these categories helps to group errors logically and allows for generalized error handling strategies.

namespace Zentient.Results
{
    /// <summary>
    /// Defines broad categories for errors, aiding in classification and generalized handling.
    /// </summary>
    public enum ErrorCategory
    {
        /// <summary>
        /// An unspecified or general error.
        /// </summary>
        General = 0,

        /// <summary>
        /// An error related to invalid input or data that failed validation rules.
        /// Corresponds to HTTP 400 Bad Request.
        /// </summary>
        Validation = 1,

        /// <summary>
        /// An error indicating that the client is not authenticated.
        /// Corresponds to HTTP 401 Unauthorized.
        /// </summary>
        Authentication = 2,

        /// <summary>
        /// An error indicating that the client is authenticated but does not have permission to perform the action.
        /// Corresponds to HTTP 403 Forbidden.
        /// </summary>
        Authorization = 3,

        /// <summary>
        /// An error indicating that the requested resource was not found.
        /// Corresponds to HTTP 404 Not Found.
        /// </summary>
        NotFound = 4,

        /// <summary>
        /// An error indicating a conflict with the current state of the resource (e.g., trying to create a duplicate).
        /// Corresponds to HTTP 409 Conflict.
        /// </summary>
        Conflict = 5,

        /// <summary>
        /// An error related to core business rules or logic that was violated.
        /// </summary>
        BusinessLogic = 6,

        /// <summary>
        /// An error representing an unexpected condition or fault within the server/application.
        /// Corresponds to HTTP 500 Internal Server Error.
        /// </summary>
        InternalError = 7,

        /// <summary>
        /// An error indicating a timeout occurred during an operation.
        /// Corresponds to HTTP 408 Request Timeout.
        /// </summary>
        Timeout = 8,

        /// <summary>
        /// An error indicating an external service dependency is unavailable or returned an error.
        /// Corresponds to HTTP 503 Service Unavailable.
        /// </summary>
        ServiceUnavailable = 9,

        /// <summary>
        /// An error indicating that the operation is not allowed in the current state of the resource.
        /// Corresponds to HTTP 405 Method Not Allowed or 409 Conflict (specific cases).
        /// </summary>
        InvalidOperation = 10,

        /// <summary>
        /// An error indicating too many requests have been made within a certain time frame.
        /// Corresponds to HTTP 429 Too Many Requests.
        /// </summary>
        TooManyRequests = 11
    }
}

Members

  • General
  • Validation
  • Authentication
  • Authorization
  • NotFound
  • Conflict
  • BusinessLogic
  • InternalError
  • Timeout
  • ServiceUnavailable
  • InvalidOperation
  • TooManyRequests

Usage Example

using Zentient.Results;

ErrorInfo error = new ErrorInfo(ErrorCategory.Validation, "EmailFormat", "Invalid email format.");

if (error.Category == ErrorCategory.Validation)
{
    Console.WriteLine("This is a client-side validation error.");
}

// Result.Validation automatically sets the category to Validation
IResult<string> result = Result.Validation<string>(new ErrorInfo[]
{
    new ErrorInfo(ErrorCategory.Validation, "PasswordTooShort", "Password must be at least 8 characters.")
});

Console.WriteLine($"Result category: {result.Errors.First().Category}");

IResultStatus Interface

The IResultStatus interface provides a contract for defining the semantic outcome of an operation. It typically includes a numeric code (often mapping to HTTP status codes) and a human-readable description. This allows for standardized status reporting beyond just success/failure.

namespace Zentient.Results
{
    /// <summary>
    /// Represents the overall semantic status of an operation result.
    /// </summary>
    public interface IResultStatus : IEquatable<IResultStatus>
    {
        /// <summary>
        /// Gets the numeric code associated with the status (e.g., HTTP status code).
        /// </summary>
        int Code { get; }

        /// <summary>
        /// Gets a descriptive message for the status.
        /// </summary>
        string Description { get; }

        /// <summary>
        /// Gets a value indicating whether this status represents a successful outcome.
        /// </summary>
        bool IsSuccess { get; }
    }
}

Properties

  • Code: int

    • Description: A numeric code representing the status. This is often an HTTP status code (e.g., 200 for OK, 404 for Not Found).
    • Usage: For programmatic status checking and mapping to external protocols (like HTTP responses).
  • Description: string

    • Description: A brief, human-readable description of the status.
    • Usage: For logging or debugging.
  • IsSuccess: bool

    • Description: Indicates whether this specific status code signifies a successful outcome. By convention, codes in the 2xx range are typically considered successful.
    • Usage: To quickly determine the success nature of a given status without checking the code range manually.

ResultStatus Struct

The ResultStatus struct is an immutable, concrete implementation of the IResultStatus interface. It provides a default way to create custom status objects if the predefined statuses in ResultStatuses are not sufficient.

namespace Zentient.Results
{
    /// <summary>
    /// Represents an immutable, concrete implementation of <see cref="IResultStatus"/>.
    /// </summary>
    public readonly struct ResultStatus : IResultStatus, IEquatable<ResultStatus>
    {
        // Properties inherited from IResultStatus (Code, Description, IsSuccess)

        /// <summary>
        /// Initializes a new instance of the <see cref="ResultStatus"/> struct.
        /// </summary>
        /// <param name="code">The numeric code for the status.</param>
        /// <param name="description">The description for the status.</param>
        /// <param name="isSuccess">Indicates if this status represents success.</param>
        public ResultStatus(int code, string description, bool isSuccess);

        // IEquatable implementation (Equals, GetHashCode)
        // Comparison operators (==, !=)
        // Override for ToString()
    }
}

Properties

  • Code: int (from IResultStatus)
  • Description: string (from IResultStatus)
  • IsSuccess: bool (from IResultStatus)

Constructor

  • ResultStatus(int code, string description, bool isSuccess)
    • Description: Initializes a new instance of ResultStatus with the specified code, description, and success indicator.

Usage Example (Creating Custom Status)

using Zentient.Results;

// Define a custom status
var createdStatus = new ResultStatus(201, "Resource Created", true);
var customBadRequest = new ResultStatus(400, "Invalid Client Request", false);

Console.WriteLine($"Custom Status: {createdStatus.Code} - {createdStatus.Description} (IsSuccess: {createdStatus.IsSuccess})");

ResultStatuses Static Class

The ResultStatuses static class provides a convenient collection of predefined, commonly used IResultStatus instances. These static properties allow for consistent and easy access to standard operation outcomes, often mirroring common HTTP status codes.

namespace Zentient.Results
{
    /// <summary>
    /// Provides a collection of predefined, commonly used <see cref="IResultStatus"/> instances.
    /// </summary>
    public static class ResultStatuses
    {
        /// <summary>
        /// Gets an <see cref="IResultStatus"/> representing a successful operation (HTTP 200 OK).
        /// </summary>
        public static IResultStatus Ok { get; }

        /// <summary>
        /// Gets an <see cref="IResultStatus"/> representing that a resource was created (HTTP 201 Created).
        /// </summary>
        public static IResultStatus Created { get; }

        /// <summary>
        /// Gets an <see cref="IResultStatus"/> representing no content (HTTP 204 No Content).
        /// </summary>
        public static IResultStatus NoContent { get; }

        // ... other successful statuses (e.g., Accepted, PartialContent)

        /// <summary>
        /// Gets an <see cref="IResultStatus"/> representing a bad request, typically due to validation errors (HTTP 400 Bad Request).
        /// </summary>
        public static IResultStatus BadRequest { get; }

        /// <summary>
        /// Gets an <see cref="IResultStatus"/> representing unauthorized access (HTTP 401 Unauthorized).
        /// </summary>
        public static IResultStatus Unauthorized { get; }

        /// <summary>
        /// Gets an <see cref="IResultStatus"/> representing forbidden access (HTTP 403 Forbidden).
        /// </summary>
        public static IResultStatus Forbidden { get; }

        /// <summary>
        /// Gets an <see cref="IResultStatus"/> representing a resource not found (HTTP 404 Not Found).
        /// </summary>
        public static IResultStatus NotFound { get; }

        /// <summary>
        /// Gets an <see cref="IResultStatus"/> representing a conflict (HTTP 409 Conflict).
        /// </summary>
        public static IResultStatus Conflict { get; }

        /// <summary>
        /// Gets an <see cref="IResultStatus"/> representing an internal server error (HTTP 500 Internal Server Error).
        /// </summary>
        public static IResultStatus InternalError { get; }

        // ... other error statuses (e.g., ServiceUnavailable, TooManyRequests, MethodNotAllowed, RequestTimeout)
    }
}

Members (Key Predefined Statuses)

  • Success Statuses:

    • Ok (Code: 200, Description: "OK", IsSuccess: true)
    • Created (Code: 201, Description: "Created", IsSuccess: true)
    • NoContent (Code: 204, Description: "No Content", IsSuccess: true)
    • Accepted (Code: 202, Description: "Accepted", IsSuccess: true)
    • PartialContent (Code: 206, Description: "Partial Content", IsSuccess: true)
  • Failure Statuses:

    • BadRequest (Code: 400, Description: "Bad Request", IsSuccess: false)
    • Unauthorized (Code: 401, Description: "Unauthorized", IsSuccess: false)
    • Forbidden (Code: 403, Description: "Forbidden", IsSuccess: false)
    • NotFound (Code: 404, Description: "Not Found", IsSuccess: false)
    • MethodNotAllowed (Code: 405, Description: "Method Not Allowed", IsSuccess: false)
    • RequestTimeout (Code: 408, Description: "Request Timeout", IsSuccess: false)
    • Conflict (Code: 409, Description: "Conflict", IsSuccess: false)
    • TooManyRequests (Code: 429, Description: "Too Many Requests", IsSuccess: false)
    • InternalError (Code: 500, Description: "Internal Server Error", IsSuccess: false)
    • ServiceUnavailable (Code: 503, Description: "Service Unavailable", IsSuccess: false)
    • GatewayTimeout (Code: 504, Description: "Gateway Timeout", IsSuccess: false)

Usage Example

using Zentient.Results;

// Check a result's status against predefined values
IResult<string> userResult = /* assume this comes from a method */;

if (userResult.Status == ResultStatuses.NotFound)
{
    Console.WriteLine("The requested user was not found.");
}
else if (userResult.Status.IsSuccess)
{
    Console.WriteLine($"Successfully retrieved user: {userResult.Value}");
}
else
{
    Console.WriteLine($"Operation failed with status: {userResult.Status.Code} {userResult.Status.Description}");
}

// When creating a result, you often use factory methods that set the status for you
IResult createResult = Result.Conflict(new ErrorInfo("UserExists", "User with this email already exists."));
Console.WriteLine($"Create result status: {createResult.Status.Description}");
⚠️ **GitHub.com Fallback** ⚠️