Kanject.Core.Adapter

View .md

The outbound HTTP integration layer. Typed HttpClient registration, resilient retries, authentication and header helpers, health pings, AOT-safe JSON overloads — plus a source generator that turns declarative endpoint contracts into production-ready adapter methods.

Use it when a service needs a stable boundary around a payment gateway, shipping carrier, CRM, internal microservice, or any other HTTP API. Application code depends on a typed adapter instead of spreading URLs, credentials, serialization, and status-code handling across controllers and domain services.

Install

bash
dotnet add package Kanject.Core.Adapter

Kanject.Core.Adapter.Annotations (the endpoint source generator) is included transitively, so generated adapters normally need no second package reference.

A generated adapter

Declare the contract — auth scheme, base URL, endpoints, per-endpoint headers — and the generator emits the adapter methods:

csharp
[AdapterAuth(    AuthScheme.ApiKey,    SettingsType = typeof(ParcelApiOptions),    HeaderMappings = ["X-Api-Key:ApiKey"])][AdapterBaseUrl(nameof(ParcelApiOptions.BaseUrl))][AdapterJsonSerializerContext(typeof(ParcelAdapterJsonContext))]public partial class ParcelAdapter(    HttpClient httpClient,    ParcelApiOptions settings) : AbstractServiceAdapter(httpClient){    private readonly ParcelApiOptions _settings = settings;    [AdapterEndpoint(HttpVerb.Post, "v1/shipments")]    [AdapterHeader("Idempotency-Key", "{request.IdempotencyKey}")]    public virtual partial Task<CreateShipmentResponse?> CreateShipmentAsync(        CreateShipmentRequest request,        CancellationToken cancellationToken);    [AdapterEndpoint(        HttpVerb.Get,        "v1/shipments/{ShipmentId}",        NotFoundReturnsNull = true)]    public virtual partial Task<ShipmentStatus?> GetShipmentAsync(        ShipmentLookup request,        CancellationToken cancellationToken);}

Two authoring styles

  • Generated endpoints — attributes, request/response DTOs, and partial method signatures. Best for most integrations and documentation-first contracts.
  • Hand-written adapter — subclass AbstractServiceAdapter and call GetAsync / PostAsync / PutAsync / DeleteAsync directly. Best for custom protocols, unusual response handling, or incremental migration.

Both styles share the same AbstractServiceAdapter, HttpClientFactory registration, retry policy, cancellation flow, and response helpers — you can mix them in one adapter.

What ships with it

  • Auth schemes — API key, bearer token, and header-mapped credentials declared once per adapter ([AdapterAuth])
  • Resilient retries — a retry policy on the shared base class, tuned for transient upstream failures
  • Settings-driven config — base URLs, keys, and header values resolve from typed options ({settings.…} templates)
  • Error behaviour per endpointNotFoundReturnsNull, custom error messages, status-code mapping
  • Health pings — a built-in upstream reachability check (opt out per adapter with [AdapterDisablePing])
  • AOT-safe JSON[AdapterJsonSerializerContext] wires source-generated serializer metadata, no reflection
Was this page helpful?