Skip to content

EN Integrations and adapters

Vinícius Campos edited this page Aug 22, 2026 · 1 revision

Integrations and adapters

Português · English home

Adapters preserve one domain model and translate it at framework boundaries.

flowchart TD
    Domain[Result or Result of T] --> Asp[Offside.AspNetCore]
    Validation[FluentValidation failures] --> FV[Offside.FluentValidation]
    FV --> Errors[Offside Errors]
    Errors --> Fast[Offside.FastEndpoint validation response]
    Asp --> Problem[OffsideProblem]
    Fast --> Problem
    Problem --> Wire[application/problem+json]
    Azure[IConfiguration resolver] --> Asp
    Json[JSON resolver] --> Asp
Loading

ASP.NET Core

ToHttpResult supports Minimal APIs and ToActionResult supports MVC. Both use the same primary-error selection, resolver and response DTO. AddOffsideAspNetCore configures only Offside options; it does not add a global exception middleware.

FluentValidation and FastEndpoints

Offside.FluentValidation converts each ValidationFailure to Error.Validation. The failure error code becomes the catalog key, with blank or default *Validator codes normalized to validation; the stable client identifier remains VALIDATION.

Offside.FastEndpoint references FastEndpoints 8.3.0. The locked restored graph resolves FluentValidation 12.1.1 transitively. UseOffside installs the validation response builder, declares OffsideProblem and application/problem+json, and adds all Offside status responses to every endpoint globally. An endpoint can opt out by calling DontProduceOffside().

SendOffsideAsync delegates to ToHttpResult(...).ExecuteAsync(...). Its CancellationToken parameter exists to fit handler signatures but is deliberately ignored; cancelling that token does not cancel response serialization.

MediatR

sequenceDiagram
    participant App as Application handler
    participant Ext as PublishDomainNotificationsAsync
    participant Pub as MediatR IPublisher
    participant Col as Scoped collector
    App->>Ext: failed Result
    loop each error in result order
        Ext->>Pub: DomainNotification(error)
        Pub->>Col: Handle(notification)
    end
    Ext-->>App: original Result
    App->>Col: ToResult() / Errors
Loading

AddOffsideMediatR idempotently registers the scoped collector and its notification handler. It does not call AddMediatR, register IPublisher, scan application handlers or configure MediatR licensing. The host must do those things first. The collector is persistent for its dependency-injection scope and returns snapshots; use one scope per logical operation.

Publishing passes the supplied cancellation token to MediatR and returns the original result. The collector de-duplicates the same notification object, which protects against the same handler instance being registered twice, but two different notification objects carrying equal errors are still distinct notifications.

Clone this wiki locally