Typed errors, validated value objects, and composable application pipelines for .NET.
Without Trellis
if (string.IsNullOrWhiteSpace(request.Email))
return Results.BadRequest(new { code = "validation.error", detail = "Email is required." });
if (!request.Email.Contains('@'))
return Results.BadRequest(new { code = "validation.error", detail = "Email is invalid." });
return Results.Ok(new User(request.Email.Trim().ToLowerInvariant()));With Trellis
using Trellis.Asp;
using Trellis.Primitives;
return EmailAddress.TryCreate(request.Email)
.Map(email => new User(email))
.ToHttpResult();Result<T>andMaybe<T>pipelines that make failures explicit.- Strongly typed value objects that remove primitive obsession.
- DDD building blocks:
Aggregate,Entity,ValueObject,Specification, and domain events. - ASP.NET Core, EF Core, Mediator, HttpClient, FluentValidation, and Stateless integrations.
- Roslyn analyzers and test helpers that keep teams on the happy path.
- AOT-friendly, allocation-conscious APIs built for modern .NET.
dotnet add package Trellis.Resultsusing Trellis;
var result = Result.Success("ada@example.com")
.Ensure(email => email.Contains('@'),
Error.Validation("Email is invalid.", "email"))
.Map(email => email.Trim().ToLowerInvariant());| Package | What it gives you |
|---|---|
| Trellis.Results | Result<T>, Maybe<T>, typed errors, and pipeline operators |
| Trellis.DomainDrivenDesign | Aggregate, Entity, ValueObject, Specification, and domain events |
| Trellis.Primitives | Ready-to-use value objects plus base classes for your own |
| Trellis.Primitives.Generator | Source generation for RequiredString<TSelf> and related primitives |
| Trellis.Analyzers | Compile-time guidance for Result, Maybe, and EF Core usage |
| Package | What it gives you |
|---|---|
| Trellis.Asp | Result-to-HTTP mapping, scalar validation, and JSON/model binding |
| Trellis.AspSourceGenerator | AOT-friendly JSON converter generation for Trellis scalar values |
| Trellis.Authorization | Actor, permission checks, and resource authorization primitives |
| Trellis.Asp.Authorization | Claims, Entra, and development actor providers for ASP.NET Core |
| Trellis.Http | HttpClient extensions that stay inside the Result pipeline |
| Trellis.Mediator | Result-aware pipeline behaviors for Mediator |
| Trellis.FluentValidation | FluentValidation output converted into Trellis results |
| Trellis.EntityFrameworkCore | EF Core conventions, converters, Maybe queries, and safe save helpers |
| Trellis.EntityFrameworkCore.Generator | Generated backing fields for Maybe<T> and owned value-object helpers |
| Trellis.Stateless | Stateless transitions that return Result<TState> |
| Trellis.Testing | FluentAssertions extensions for Result<T> and Maybe<T> |
Typical overhead is measured in single-digit to low double-digit nanoseconds—tiny next to a database call or HTTP request. Benchmarks
Contributions are welcome. For major changes, please open an issue first and run dotnet test before sending a PR.
