Offside

offside

Offside documentation

catch it before the whistle · Português

NuGet Downloads CI License Frameworks

Domain errors as Result, not exceptions. The domain returns an Error; ASP.NET Core maps it to Problem Details (RFC 7807). Messages live in JSON catalogs, not in C#.

Prefer a browsable guide with architecture diagrams? Visit the English Wiki or the Portuguese Wiki.

Start here

Page What it covers
Getting started Install, register, and return your first Problem Details response
Concepts Error, ErrorCode, ErrorKind, Result, primary error, catalogs, the escape hatch
Domain guide Writing domain code with Result<T>: factories, Custom, Bind/Map/Combine
ASP.NET Core guide ToHttpResult / ToActionResult, status selection, the response shape, 500 handling
FluentValidation Map FluentValidation failures to Offside Error / Result
FastEndpoints UseOffside, SendOffsideAsync, OpenAPI expected errors
MediatR integration Publish result errors as notifications, collect them per scope, and handle retries safely
Refit integration Turn an external API failure into an Error, without a try/catch at every call site
Application Insights Record domain errors as traces with severity and stable dimensions
OpenTelemetry Record domain errors through OpenTelemetry, for hosts using Azure.Monitor.OpenTelemetry or an OTLP exporter
Querying domain errors Kusto filters on offside.code / offside.errorCode / offside.kind — there is no {OriginalFormat}
Messages and cultures Catalog format, culture fallback, {token} interpolation
Testing guide Assert Result, Error, and message catalogs in unit tests
CLI offside init — agent skills and catalog templates
API reference Every public type and member, in one page
FAQ Design decisions and common pitfalls

The shape of it

// Domain — knows nothing about HTTP
public Result<Order> Get(string id)
{
    var order = _orders.Find(id);
    return order is null
        ? Result<Order>.Failure(Error.NotFound("order", id))
        : Result<Order>.Success(order);
}
// Endpoint — one line
app.MapGet("/orders/{id}", (string id, HttpContext http) => _orders.Get(id).ToHttpResult(http));
// Response — 404, application/problem+json
{
  "type": "https://httpstatuses.io/404",
  "title": "NotFound",
  "status": 404,
  "detail": "order '42' was not found.",
  "errorCode": "NOT_FOUND",
  "traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
  "errors": [
    { "code": "not_found", "errorCode": "NOT_FOUND", "kind": "NotFound", "detail": "order '42' was not found.", "field": null }
  ]
}

Packages

Package Version Target frameworks Role
Offside NuGet netstandard2.0, net8.0, net10.0 Error, ErrorKind, Result / Result<T>, JSON resolver, AddOffside
Offside.AspNetCore NuGet net8.0, net10.0 ToHttpResult / ToActionResult, Problem Details, AddOffsideAspNetCore
Offside.FluentValidation NuGet netstandard2.0, net8.0, net10.0 FluentValidation failures → Error / Result
Offside.FastEndpoint NuGet net8.0, net10.0 UseOffside, SendOffsideAsync, OpenAPI expected errors
Offside.AzureAppConfiguration NuGet netstandard2.0, net8.0, net10.0 Dynamic resolver for catalogs loaded by Azure App Configuration
Offside.MediatR NuGet netstandard2.0, net8.0, net10.0 MediatR notifications for failed results and a scoped collector
Offside.Testing NuGet netstandard2.0, net8.0, net10.0 Assertions for Result, Error, and message catalogs, with no test-framework dependency
Offside.Refit NuGet netstandard2.0, net8.0, net10.0 Refit failures from an external API mapped to Error / Result
Offside.ApplicationInsights NuGet netstandard2.0, net8.0, net10.0 Domain errors recorded as Application Insights traces
Offside.ApplicationInsights.MediatR NuGet netstandard2.0, net8.0, net10.0 Bridge recording published domain notifications as telemetry
Offside.Tool NuGet net8.0 offside init — agent skills and catalog templates

The core package has no ASP.NET or MediatR dependency, so domain projects can reference it freely.

Elsewhere