Gasolutions.Core.Patterns.Result 2.0.0.1

dotnet add package Gasolutions.Core.Patterns.Result --version 2.0.0.1
                    
NuGet\Install-Package Gasolutions.Core.Patterns.Result -Version 2.0.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Gasolutions.Core.Patterns.Result" Version="2.0.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Gasolutions.Core.Patterns.Result" Version="2.0.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Gasolutions.Core.Patterns.Result" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Gasolutions.Core.Patterns.Result --version 2.0.0.1
                    
#r "nuget: Gasolutions.Core.Patterns.Result, 2.0.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Gasolutions.Core.Patterns.Result@2.0.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Gasolutions.Core.Patterns.Result&version=2.0.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Gasolutions.Core.Patterns.Result&version=2.0.0.1
                    
Install as a Cake Tool

Gasolutions.Core.Patterns.Result

Español · English


<a name="español"></a>

🇪🇸 Español

Implementación del patrón Result para .NET 9. Permite manejar resultados y errores de forma explícita, evitando el uso de excepciones para flujos de control y proporcionando información contextual precisa sobre el origen del error.

Instalación

dotnet add package Gasolutions.Core.Patterns.Result

Clases principales

Clase Descripción
Result Resultado sin valor de retorno
Result<T> Resultado con valor de retorno tipado
ResultResponse<T> DTO serializable para respuestas HTTP/API
Error Registro inmutable que describe un error
ErrorLanguage Configura el idioma de los mensajes (por defecto: español)

Inicio rápido

Retornar un éxito

public Result CrearUsuario(string nombre)
{
    // ... lógica de negocio
    return Result.Success();
}

public Result<Usuario> ObtenerUsuario(int id)
{
    var usuario = _repo.FindById(id);
    if (usuario is null)
        return Result<Usuario>.Failure(DatabaseErrors.NotFound("Usuario", id));

    return Result<Usuario>.Success(usuario);
}

Retornar un error

public Result<Producto> ObtenerProducto(int id)
{
    var producto = _db.Productos.Find(id);
    if (producto is null)
        return Result<Producto>.Failure(DatabaseErrors.NotFound("Producto", id));

    return Result<Producto>.Success(producto);
}

Consumir el resultado

var resultado = ObtenerProducto(42);

if (resultado.IsFailure)
{
    Console.WriteLine($"Error [{resultado.Error.Code}]: {resultado.Error.Description}");
    Console.WriteLine($"Origen: {resultado.Error.ClassName}.{resultado.Error.MethodName}");
    return;
}

Console.WriteLine($"Producto: {resultado.Value.Nombre}");

Usar ResultResponse<T> en una API

[HttpGet("{id}")]
public IActionResult GetProducto(int id)
{
    var resultado = _service.ObtenerProducto(id);

    if (resultado.IsFailure)
        return NotFound(new ResultResponse<Producto>
        {
            IsFailure = true,
            Error = resultado.Error
        });

    return Ok(new ResultResponse<Producto>
    {
        IsSuccess = true,
        Value = resultado.Value
    });
}

Fábricas de errores disponibles

Fábrica Cuándo usarla
ArgumentErrors Argumentos inválidos en métodos
AuthErrors Autenticación y autorización
AzureStorageErrors Azure Blob Storage
CommunicationErrors Conexión a servicios externos
ContainerErrors Validación de contenedores y archivos
DatabaseErrors Acceso a datos y consultas
EmailErrors Proveedor de correo electrónico
EnviromentVariableErrors Variables de entorno
ExceptionErrors Excepciones no controladas
HttpErrors Comunicación HTTP
KeyValueErrors Claves inválidas
OtherErrors Errores misceláneos
TokenErrors Obtención de tokens
TwoFactorErrors Autenticación de dos factores

Ejemplos por fábrica

// ArgumentErrors
ArgumentErrors.NoValid("string", "correo", "no tiene formato válido");

// AuthErrors
AuthErrors.InvalidCredentials();
AuthErrors.UserBlocked("jgalviz");
AuthErrors.InsufficientPermissions();
AuthErrors.SamlConfigNotFound(companyId: 5);

// AzureStorageErrors
AzureStorageErrors.BlobNotFound("mi-contenedor", "archivo.pdf");

// CommunicationErrors
CommunicationErrors.CommunicationError("PaymentService", "timeout después de 30s");

// ContainerErrors
ContainerErrors.InvalidContainerName();
ContainerErrors.LocalFileNotFound("/tmp/reporte.pdf");

// DatabaseErrors
DatabaseErrors.NotFound("Factura", 1001);                            // por ID
DatabaseErrors.NotFound("Factura", "NumeroFactura", "F-2024-001");   // por campo y valor
DatabaseErrors.NotFound("Caja", "CodigoCaja", isMale: false);        // género femenino
DatabaseErrors.TableWithoutRegisters("Producto");
DatabaseErrors.NotUpdated("Pedido", 55, "registro bloqueado");
DatabaseErrors.AssociatedRegisters("CajaVenta", stationId: 3);
DatabaseErrors.ForeingRelationViolated("el mensaje de error del motor de BD");

// EmailErrors
EmailErrors.InvalidResponse();
EmailErrors.InvalidResponse("SMTP 550: buzón lleno");
EmailErrors.Others("El proveedor rechazó el adjunto");   // mensaje libre

// EnviromentVariableErrors
EnviromentVariableErrors.NoFound("CONNECTION_STRING");

// ExceptionErrors
ExceptionErrors.ExceptionNotControlled(ex);
ExceptionErrors.ExceptionNotControlledInvokingServiceMethod("UserService", ex);

// HttpErrors
HttpErrors.UnAuthorized("https://api.pagos.com/cobros");
HttpErrors.BadResponse("FacturaDto", responseBody);
HttpErrors.InternalServerError(responseBody);            // mensaje del servidor, no localizado

// KeyValueErrors
KeyValueErrors.NoValid("clave-inv@lida");

// OtherErrors
OtherErrors.NotDefined("Ocurrió algo inesperado");       // mensaje libre
OtherErrors.CommunicationError(["ServicioA", "ServicioB"]);
OtherErrors.MessageMismatch(["ok", "procesado"], ["error", "timeout"]);

// TokenErrors
TokenErrors.GettingProblem("IdentityServer");

// TwoFactorErrors
TwoFactorErrors.EmailNotConfirmed();
TwoFactorErrors.UserNotFound("jgalviz");
TwoFactorErrors.OtpInvalid();
TwoFactorErrors.OtpExpired();
TwoFactorErrors.InvalidCredentials();

Soporte de idiomas (Español / Inglés)

Por defecto la librería devuelve todos los mensajes en español. Para cambiar el idioma usa ErrorLanguage.Current:

using System.Globalization;
using Gasolutions.Core.Patterns.Result.Localization;

// Cambiar a inglés
ErrorLanguage.Current = new CultureInfo("en");

// Volver a español
ErrorLanguage.Current = new CultureInfo("es");

Ejemplo de salida por idioma

// --- Español (por defecto) ---
var err = DatabaseErrors.NotFound("Producto", 42);
// Description → "Producto 42 no fue encontrado."

// --- Inglés ---
ErrorLanguage.Current = new CultureInfo("en");
var err = DatabaseErrors.NotFound("Product", 42);
// Description → "Product 42 was not found."

Configuración global en ASP.NET Core

Configura el idioma una sola vez en el arranque de la aplicación:

// Program.cs
ErrorLanguage.Current = new CultureInfo(
    builder.Configuration["AppLanguage"] ?? "es"
);

Nota: Los mensajes que son texto libre del llamador (p. ej., OtherErrors.NotDefined, AuthErrors.RequiredField, HttpErrors.InternalServerError) no se localizan; la librería los pasa tal cual.


La estructura del Error

public sealed record Error(
    string Code,         // Código auto-generado: "NombreClase.NombreMetodo"
    string Description,  // Mensaje localizado o texto del llamador
    string ClassName,    // Clase que invocó la fábrica
    string MethodName    // Método que invocó la fábrica
);

Ejemplo de inspección

var error = DatabaseErrors.NotFound("Orden", 99);

Console.WriteLine(error.Code);        // "DatabaseErrors.NotFound"
Console.WriteLine(error.Description); // "Orden 99 no fue encontrada."
Console.WriteLine(error.ClassName);   // Clase del llamador
Console.WriteLine(error.MethodName);  // Método del llamador

Patrón recomendado en capas

// Capa de dominio / servicio
public Result<Pedido> ProcesarPedido(int pedidoId)
{
    var pedido = _repo.Find(pedidoId);
    if (pedido is null)
        return Result<Pedido>.Failure(DatabaseErrors.NotFound("Pedido", pedidoId));

    if (!pedido.PuedesProcesarse())
        return Result<Pedido>.Failure(OtherErrors.NotDefined("El pedido no está en estado válido para procesarse."));

    pedido.Procesar();
    _repo.Save(pedido);
    return Result<Pedido>.Success(pedido);
}

// Capa de API
[HttpPost("{id}/procesar")]
public IActionResult Procesar(int id)
{
    var resultado = _service.ProcesarPedido(id);

    return resultado.IsSuccess
        ? Ok(resultado.Value)
        : BadRequest(resultado.Error);
}

<a name="english"></a>

🇺🇸 English

Result pattern implementation for .NET 9. Provides explicit handling of operation results and errors — avoiding exceptions for flow control — with precise contextual information about where each error originated.

Installation

dotnet add package Gasolutions.Core.Patterns.Result

Core classes

Class Description
Result Result without a return value
Result<T> Result with a typed return value
ResultResponse<T> Serializable DTO for HTTP/API responses
Error Immutable record describing an error
ErrorLanguage Configures the message language (default: Spanish)

Quick start

Returning success

public Result CreateUser(string name)
{
    // ... business logic
    return Result.Success();
}

public Result<User> GetUser(int id)
{
    var user = _repo.FindById(id);
    if (user is null)
        return Result<User>.Failure(DatabaseErrors.NotFound("User", id));

    return Result<User>.Success(user);
}

Returning an error

public Result<Product> GetProduct(int id)
{
    var product = _db.Products.Find(id);
    if (product is null)
        return Result<Product>.Failure(DatabaseErrors.NotFound("Product", id));

    return Result<Product>.Success(product);
}

Consuming the result

var result = GetProduct(42);

if (result.IsFailure)
{
    Console.WriteLine($"Error [{result.Error.Code}]: {result.Error.Description}");
    Console.WriteLine($"Origin: {result.Error.ClassName}.{result.Error.MethodName}");
    return;
}

Console.WriteLine($"Product: {result.Value.Name}");

Using ResultResponse<T> in an API

[HttpGet("{id}")]
public IActionResult GetProduct(int id)
{
    var result = _service.GetProduct(id);

    if (result.IsFailure)
        return NotFound(new ResultResponse<Product>
        {
            IsFailure = true,
            Error = result.Error
        });

    return Ok(new ResultResponse<Product>
    {
        IsSuccess = true,
        Value = result.Value
    });
}

Available error factories

Factory When to use
ArgumentErrors Invalid method arguments
AuthErrors Authentication and authorization
AzureStorageErrors Azure Blob Storage
CommunicationErrors External service connectivity
ContainerErrors Container and file validation
DatabaseErrors Data access and queries
EmailErrors Email provider
EnviromentVariableErrors Environment variables
ExceptionErrors Unhandled exceptions
HttpErrors HTTP communication
KeyValueErrors Invalid keys
OtherErrors Miscellaneous errors
TokenErrors Token acquisition
TwoFactorErrors Two-factor authentication

Language support (Spanish / English)

By default all messages are in Spanish. Switch languages with ErrorLanguage.Current:

using System.Globalization;
using Gasolutions.Core.Patterns.Result.Localization;

// Switch to English
ErrorLanguage.Current = new CultureInfo("en");

// Back to Spanish
ErrorLanguage.Current = new CultureInfo("es");

Sample output per language

// --- Spanish (default) ---
var err = DatabaseErrors.NotFound("Producto", 42);
// Description → "Producto 42 no fue encontrado."

// --- English ---
ErrorLanguage.Current = new CultureInfo("en");
var err = DatabaseErrors.NotFound("Product", 42);
// Description → "Product 42 was not found."

Global setup in ASP.NET Core

// Program.cs
ErrorLanguage.Current = new CultureInfo(
    builder.Configuration["AppLanguage"] ?? "es"
);

Note: Caller-supplied free-text messages (e.g., OtherErrors.NotDefined, AuthErrors.RequiredField, HttpErrors.InternalServerError) are not localized by the library — they are passed through as-is.


The Error record structure

public sealed record Error(
    string Code,         // Auto-generated: "ClassName.MethodName"
    string Description,  // Localized message or caller-supplied text
    string ClassName,    // Class that called the factory
    string MethodName    // Method that called the factory
);

// Domain / service layer
public Result<Order> ProcessOrder(int orderId)
{
    var order = _repo.Find(orderId);
    if (order is null)
        return Result<Order>.Failure(DatabaseErrors.NotFound("Order", orderId));

    if (!order.CanBeProcessed())
        return Result<Order>.Failure(OtherErrors.NotDefined("Order is not in a valid state for processing."));

    order.Process();
    _repo.Save(order);
    return Result<Order>.Success(order);
}

// API layer
[HttpPost("{id}/process")]
public IActionResult Process(int id)
{
    var result = _service.ProcessOrder(id);

    return result.IsSuccess
        ? Ok(result.Value)
        : BadRequest(result.Error);
}

License

MIT © Gasolutions SAS

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net9.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Gasolutions.Core.Patterns.Result:

Package Downloads
Gasolutions.Core.Interfaces.Ports

Ports for Clean Architecture.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0.1 143 5/24/2026
2.0.0 128 5/24/2026
1.0.10.1 126 5/20/2026
1.0.10 124 5/20/2026
1.0.9 147 2/19/2026
1.0.8.1 136 2/15/2026
1.0.8 128 2/13/2026
1.0.7 138 2/13/2026
1.0.6 146 2/10/2026
1.0.1 131 2/9/2026
1.0.0 129 2/9/2026

# Changelog - Gasolutions.Core.Patterns.Result
All notable changes to this project will be documented in this file.
## [2.0.1.0]
### Added
- `Error.AppendToDescription(string text)` — returns a new immutable `Error` instance with the given text appended to the existing description (uses `record` `with` expression)
- `Error.AddToDescription(string text)` — returns a new immutable `Error` instance with the given text inserted to the existing description (uses `record` `with` expression)
## [2.0.0.0]
### Added
- `ErrorLanguage` static class to configure the active culture for error messages (defaults to Spanish `es`)
- `ErrorMessages` internal helper that resolves localized message templates via `ResourceManager`
- `Messages.resx` embedded resource with 38 Spanish message templates (default language)
- `Messages.en.resx` embedded resource with 38 English message templates
- Bilingual support (Spanish / English) across all error factories: `ArgumentErrors`, `AuthErrors`, `AzureStorageErrors`, `CommunicationErrors`, `ContainerErrors`, `DatabaseErrors`, `EmailErrors`, `EnviromentVariableErrors`, `HttpErrors`, `KeyValueErrors`, `OtherErrors`, `TokenErrors`, `TwoFactorErrors`
### Changed
- All fixed error message strings in error factories replaced with `ErrorMessages.Get(key, args)` resource lookups
- Caller-supplied messages (`OtherErrors.NotDefined`, `AuthErrors.RequiredField`, `EmailErrors.Others`, `HttpErrors.InternalServerError`, `HttpErrors.General`, `ExceptionErrors.*`) remain unchanged — they are not localized by the library
- `Error.Create(...)` centralizes `StackTraceHelper.RetrieveCallerInfo()` — no longer called directly from factory classes
- `StackTraceHelper.RetrieveCallerInfo(int frameOffset = 0)` now accepts a frame offset to compensate for wrapper calls
## [1.0.10.1]
### Added
- Add KeyValue errors
- Add Email errors
## [1.0.10.0]
### Added
- Add Autentications errors
- Add Azure Storage errors
- Add Enviroment errors
- Add HTTP errors
### Changed
- StackTraceHelper is public now
## [1.0.9.0]
### Added
- Add CassName and Method Name for better error context
- New error code generation strategy using StackTraceHelper for more accurate error tracking
## [1.0.8.1]
### Added
- Add NotFound method for string field in DatabaseErrors
## [1.0.8]
### Added
- Add CHANGELOG.md file to document changes and updates
## [1.0.7]
### Added
- Comprehensive XML documentation for all error factories
- Automatic error code generation using StackTraceHelper
- Support for multiple error types with builder patterns
- Complete test suites for ArgumentErrors, CommunicationErrors, DatabaseErrors, ExceptionErrors, and OtherErrors
- Enhanced exception context preservation
- Detailed error reporting with exception hierarchy support
### Changed
- Improved StackTraceInfo encapsulation with private properties
- Enhanced error messages with better formatting
- Updated documentation to English for international audience
- Refactored error factories for consistency
### Fixed
- Error code generation accuracy
- Null reference handling in error creation
- Exception context tracking improvements
### Documentation
- Added comprehensive XML documentation for all error factories
- Created test suite documentation with 50+ test cases
- Updated inline code comments in English
---
## [1.0.6]
### Initial Release
- Basic Result pattern implementation
- Generic Result<T> class
- Non-generic Result class
- Error handling with Error record
- ArgumentErrors factory for validation errors
- DatabaseErrors factory for data access errors
- CommunicationErrors factory for service communication errors
- ExceptionErrors factory for exception handling
- OtherErrors factory for undefined scenarios