Resultia 1.0.0

dotnet add package Resultia --version 1.0.0
                    
NuGet\Install-Package Resultia -Version 1.0.0
                    
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="Resultia" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Resultia" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Resultia" />
                    
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 Resultia --version 1.0.0
                    
#r "nuget: Resultia, 1.0.0"
                    
#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 Resultia@1.0.0
                    
#: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=Resultia&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Resultia&version=1.0.0
                    
Install as a Cake Tool

Resultia

A lightweight Result pattern library for .NET.

Instead of throwing exceptions for expected failures or returning nulls, your methods return a Result that explicitly represents success or failure.


Installation

dotnet add package Resultia

Namespaces

using Resultia;          // Result, Error, HttpError
using Resultia.Generics; // Result<T>

Core Types

Type Use when
Result Operation succeeds or fails with no return value (delete, update)
Result<T> Operation succeeds with data or fails (get, create)
Error Base error type — extend it for your own error types
HttpError Built-in HTTP error type with status code and status text

Basic Usage

// Void operation
var result = Result.Success();
var result = Result.Failure(HttpError.NotFound("Book not found"));

// With data
var result = Result<Book>.Success(book);
var result = Result<Book>.Failure(HttpError.NotFound("Book not found"));

// Implicit operators — return data or error directly
public Result<Book> GetById(int id)
{
    var book = _books.FirstOrDefault(b => b.Id == id);
    if (book is null)
    {
        return HttpError.NotFound($"Book with id {id} not found");
    }

    return book;
}

Methods

Match()

Handles both cases exhaustively. Forces you to handle success and failure.

// Result
return result.Match(
    onSuccess: this.NoContent,
    onFailure: error => this.NotFound(error.Message));

// Result<T>
return result.Match(
    onSuccess: book => this.Ok(book),
    onFailure: error => this.NotFound(error.Message));

Then()

Chains operations where each step can fail. If any step fails, subsequent steps are skipped and the error is carried forward.

return GetUser(id)
    .Then(user => ValidateUser(user))
    .Then(user => SaveUser(user))
    .Match(
        onSuccess: this.Ok,
        onFailure: error => this.BadRequest(error.Message));

Map()

Transforms the data inside a Result<T> without wrapping in a Result. The callback cannot fail.

return Result<Book>.Success(book)
    .Map(b => b.Title)        // Result<string>
    .Match(
        onSuccess: title => this.Ok(title),
        onFailure: error => this.NotFound(error.Message));

OnSuccess() / OnFailure()

Side effect hooks — useful for logging. The result passes through unchanged.

return service
    .GetAll()
    .OnSuccess(books => logger.LogInformation("Returned {Count} books", books.Count))
    .OnFailure(error => logger.LogWarning("Failed: {Message}", error.Message))
    .Match(
        onSuccess: books => this.Ok(books),
        onFailure: error => this.Unauthorized(error.Message));

Async

Every method has an async counterpart: MatchAsync, ThenAsync, MapAsync, OnSuccessAsync, OnFailureAsync.

// Async Then
var result = await Result<User>
    .Success(user)
    .ThenAsync(u => SaveAsync(u));

// Async Match
var outcome = await result.MatchAsync(
    onSuccess: u => Task.FromResult(u.Name),
    onFailure: error => Task.FromResult(error.Message));

For async service calls, await the result first then chain sync methods:

var result = await service.GetAllAsync();

return result
    .OnSuccess(books => logger.LogInformation("Returned {Count} books", books.Count))
    .Match<ActionResult<IList<Book>>>(
        onSuccess: books => this.Ok(books),
        onFailure: error => this.Unauthorized(error.Message));

Custom Errors

Extend Error for your own error types:

public sealed class ValidationError(
    string field,
    string message) : Error(message)
{
    public string Field { get; } = field;
}

// Usage
var error = new ValidationError("Title", "Title is required");
return Result<Book>.Failure(error);

HttpError

Built-in error type covering all common HTTP status codes.

HttpError.BadRequest("Invalid input");
HttpError.Unauthorized("Not authenticated");
HttpError.Forbidden("Not authorized");
HttpError.NotFound("Resource not found");
HttpError.Conflict("Resource already exists");
HttpError.UnprocessableEntity("Validation failed");
HttpError.InternalServerError("Something went wrong");
// ...and more

Each HttpError exposes StatusCode and StatusText alongside the base Message.


ASP.NET Core Example

public class BookService(IRepository<Book> books) : IBookService
{
    public Result<Book> GetById(int id)
    {
        var book = books.FirstOrDefault(b => b.Id == id);
        if (book is null)
        {
            return HttpError.NotFound($"Book with id {id} not found");
        }

        return book;
    }

    public Result Delete(int id)
    {
        var book = books.FirstOrDefault(b => b.Id == id);
        if (book is null)
        {
            return HttpError.NotFound($"Book with id {id} not found");
        }

        books.Remove(book);
        return Result.Success();
    }
}

[ApiController]
[Route("api/[controller]")]
public class BooksController(IBookService service) : ControllerBase
{
    [HttpGet("{id:int}")]
    public ActionResult<Book> GetById(int id)
        => service
            .GetById(id)
            .Match<ActionResult<Book>>(
                onSuccess: book => this.Ok(book),
                onFailure: error =>
                    error is HttpError httpError && httpError.StatusCode == 401
                        ? this.Unauthorized(error.Message)
                        : this.NotFound(error.Message));

    [HttpDelete("{id:int}")]
    public ActionResult Delete(int id)
        => service
            .Delete(id)
            .OnSuccess(
                () => logger.LogInformation("Book {Id} deleted", id))
            .OnFailure(
                error => logger.LogWarning("Delete failed: {Message}", error.Message))
            .Match<ActionResult>(
                onSuccess: this.NoContent,
                onFailure: error =>
                    error is HttpError httpError && httpError.StatusCode == 401
                        ? this.Unauthorized(error.Message)
                        : this.NotFound(error.Message));
}
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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.
  • net10.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Resultia:

Package Downloads
Resultia.AspNetCore

ASP.NET Core integration for Resultia — ToActionResult() extension methods and DI registration.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 44 5/1/2026