Resultia 1.0.0
dotnet add package Resultia --version 1.0.0
NuGet\Install-Package Resultia -Version 1.0.0
<PackageReference Include="Resultia" Version="1.0.0" />
<PackageVersion Include="Resultia" Version="1.0.0" />
<PackageReference Include="Resultia" />
paket add Resultia --version 1.0.0
#r "nuget: Resultia, 1.0.0"
#:package Resultia@1.0.0
#addin nuget:?package=Resultia&version=1.0.0
#tool nuget:?package=Resultia&version=1.0.0
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 | Versions 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. |
-
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 |