Offside.Testing
0.5.0
See the version list below for details.
dotnet add package Offside.Testing --version 0.5.0
NuGet\Install-Package Offside.Testing -Version 0.5.0
<PackageReference Include="Offside.Testing" Version="0.5.0" />
<PackageVersion Include="Offside.Testing" Version="0.5.0" />
<PackageReference Include="Offside.Testing" />
paket add Offside.Testing --version 0.5.0
#r "nuget: Offside.Testing, 0.5.0"
#:package Offside.Testing@0.5.0
#addin nuget:?package=Offside.Testing&version=0.5.0
#tool nuget:?package=Offside.Testing&version=0.5.0

Offside
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
Install
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 init
offside 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.
Compatibility and status
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.
The project is pre-1.0. Minor releases may include breaking changes. Releases follow Semantic Versioning, and notable changes are recorded in CHANGELOG.md.
Packages
The Core package has no ASP.NET, MediatR, Refit, or Application Insights dependency.
Example
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
Pack locally
dotnet pack -c Release -o artifacts
Produces 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 and publish
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.0
Spec
The internal design specification records the original decisions (in Portuguese). For usage, prefer the documentation.
Community and security
Read CONTRIBUTING.md before opening a pull request. For help, see SUPPORT.md. Report vulnerabilities privately according to SECURITY.md.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.