catch it before the whistle
Domain errors as Result, not exceptions. The domain returns Error; ASP.NET Core maps that to Problem Details (RFC 7807). Messages live in JSON catalogs, not in C#.
Documentation · Wiki · Português · Wiki em português
dotnet add package Offside
dotnet add package Offside.AspNetCore # ASP.NET hosts only
dotnet add package Offside.FluentValidation # FluentValidation → Error
dotnet add package Offside.FastEndpoint # FastEndpoints hosts only
dotnet add package Offside.AzureAppConfiguration # Azure App Configuration catalogs
dotnet add package Offside.MediatR # domain notifications for failed results
dotnet add package Offside.Testing # assertions for unit tests
dotnet add package Offside.Refit # Refit clients calling external APIs
dotnet add package Offside.ApplicationInsights # domain errors as telemetry (classic SDK)
dotnet add package Offside.OpenTelemetry # domain errors as telemetry (OpenTelemetry)Agent skills + catalog templates:
dotnet tool install -g Offside.Tool
offside initoffside init copies ten skills into .cursor/skills, .agents/skills, and .claude/skills, and writes errors/errors.json plus errors/errors.pt-BR.json. The setup, implementation, and refactoring skills ask the user to select a message source (JSON, Azure, or custom), an exposure mode (domain only, ASP.NET Core, or FastEndpoints), and optional FluentValidation. Setup also offers optional MediatR domain notifications. Use --dir <path> and --force as needed.
Offside, Offside.FluentValidation, Offside.AzureAppConfiguration, Offside.MediatR, Offside.Testing, Offside.Refit, Offside.ApplicationInsights, Offside.ApplicationInsights.MediatR, Offside.OpenTelemetry, and Offside.OpenTelemetry.MediatR support netstandard2.0, net8.0, and net10.0. Offside.AspNetCore and Offside.FastEndpoint support net8.0 and net10.0; Offside.Tool runs on net8.0. Offside.MediatR, Offside.ApplicationInsights.MediatR, and Offside.OpenTelemetry.MediatR support MediatR 12.0.1 through 14.x; Offside.Refit supports Refit 8.x through 15.x ([8.0.0,16.0.0); Refit 5.x is not supported); Offside.FastEndpoint requires FastEndpoints 8.3 or later.
The project is pre-1.0. Minor releases may include breaking changes. Releases follow Semantic Versioning, and notable changes are recorded in CHANGELOG.md.
The Core package has no ASP.NET, MediatR, Refit, or Application Insights dependency.
using System.Globalization;
using Offside;
using Offside.AspNetCore;
builder.Services.AddOffside(options =>
{
options.AddJsonFile(CultureInfo.InvariantCulture, "errors/errors.json");
});
builder.Services.AddOffsideAspNetCore();
Result GetOrder(string id) =>
Result.Failure(Error.NotFound("Order", id));
app.MapGet("/orders/{id}", (string id, HttpContext http) =>
GetOrder(id).ToHttpResult(http));With AddOffsideOpenTelemetry or AddOffsideApplicationInsights registered, that one line also records the failure. There is no RecordTo at the HTTP endpoint.
MediatR hosts can publish every error in a failed result, in order, and read them back from a scoped collector:
builder.Services.AddMediatR(configuration =>
configuration.RegisterServicesFromAssemblyContaining<Program>());
builder.Services.AddOffsideMediatR();
Result result = CancelOrder(id);
return await result.PublishDomainNotificationsAsync(publisher, cancellationToken);A failure becomes application/problem+json, with the status taken from the most severe error present:
{
"type": "https://httpstatuses.io/404",
"title": "NotFound",
"status": 404,
"detail": "Order '42' was not found.",
"errorCode": "NOT_FOUND",
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
"errors": [
{ "code": "not_found", "errorCode": "NOT_FOUND", "kind": "NotFound", "detail": "Order '42' was not found.", "field": null }
]
}| ErrorKind | Status | ErrorKind | Status | |
|---|---|---|---|---|
Unexpected |
500 | Gone |
410 | |
Unauthorized |
401 | Unprocessable |
422 | |
Forbidden |
403 | NotFound |
404 | |
TooManyRequests |
429 | Validation |
400 | |
Conflict |
409 | BadRequest |
400 | |
PreconditionFailed |
412 | ServiceUnavailable |
503 | |
Timeout |
504 |
Full guides: getting started · concepts · domain · ASP.NET Core · FluentValidation · FastEndpoints · MediatR · messages · API reference
dotnet pack -c Release -o artifactsProduces Offside, Offside.AspNetCore, Offside.FluentValidation, Offside.FastEndpoint, Offside.AzureAppConfiguration, Offside.MediatR, Offside.Testing, Offside.Refit, Offside.ApplicationInsights, Offside.ApplicationInsights.MediatR, Offside.OpenTelemetry, Offside.OpenTelemetry.MediatR, and Offside.Tool nupkgs (plus snupkgs).
CI builds, tests (net8 + net10), and packs on master and pull requests.
To publish to nuget.org, add a Trusted Publishing policy:
- Repository Owner:
vpcmps - Repository:
Offside - Workflow File:
release.yml - Environment: leave blank
Then push a version tag (the tag is the package version):
git tag v0.3.0
git push origin v0.3.0The internal design specification records the original decisions (in Portuguese). For usage, prefer the documentation.
Read CONTRIBUTING.md before opening a pull request. For help, see SUPPORT.md. Report vulnerabilities privately according to SECURITY.md.
