Raycynix.Extensions.Contracts.AspNetCore
2.2.0
dotnet add package Raycynix.Extensions.Contracts.AspNetCore --version 2.2.0
NuGet\Install-Package Raycynix.Extensions.Contracts.AspNetCore -Version 2.2.0
<PackageReference Include="Raycynix.Extensions.Contracts.AspNetCore" Version="2.2.0" />
<PackageVersion Include="Raycynix.Extensions.Contracts.AspNetCore" Version="2.2.0" />
<PackageReference Include="Raycynix.Extensions.Contracts.AspNetCore" />
paket add Raycynix.Extensions.Contracts.AspNetCore --version 2.2.0
#r "nuget: Raycynix.Extensions.Contracts.AspNetCore, 2.2.0"
#:package Raycynix.Extensions.Contracts.AspNetCore@2.2.0
#addin nuget:?package=Raycynix.Extensions.Contracts.AspNetCore&version=2.2.0
#tool nuget:?package=Raycynix.Extensions.Contracts.AspNetCore&version=2.2.0
Raycynix.Extensions.Contracts.AspNetCore
Raycynix.Extensions.Contracts.AspNetCore adds ASP.NET Core integration for the shared contract types defined in Raycynix.Extensions.Contracts.
What it contains
- endpoint metadata for declared contract identities
- middleware for writing contract headers to HTTP responses
- helpers for reading contract headers from incoming requests
- minimal API helpers for contract-aware HTTP results
- MVC helpers for converting
ModelStateintoErrorContract - optional Microsoft.Extensions.Logging diagnostics for contract middleware and result execution
Installation
builder.Services.AddRaycynixContractsAspNetCore();
var app = builder.Build();
app.UseRaycynixContracts();
Response Shape Options
Use plain contract results when you want headers plus the original response body:
app.MapGet("/catalog/prices/{id}", (HttpContext httpContext) =>
httpContext.Contract(new Money
{
Amount = 149.99m,
Currency = "USD"
}))
.WithContract("catalog.prices", "1.2.0");
Use VersionedContract(...) when you want the body wrapped into VersionedContract<T>.
How It Works
Contract support in ASP.NET Core has two separate parts:
- endpoint metadata, which declares the contract name and version for the HTTP endpoint
- response shaping, which decides whether the body is a plain DTO or a
VersionedContract<T>
When you declare a contract on an endpoint, the middleware writes these response headers automatically:
X-Contract-NameX-Contract-Version
Use the result helpers only when you also want the response body to follow a contract-aware shape.
Minimal API
Declare contract metadata directly on the endpoint:
app.MapGet("/catalog/prices", () =>
httpContext => httpContext.VersionedContract(
new[] { new Money { Amount = 149.99m, Currency = "USD" } }))
.WithContract("catalog.prices", "1.2.0");
WithContract(...) declares the endpoint contract metadata.
httpContext.VersionedContract(...) reads that metadata from the current endpoint, wraps the response body into VersionedContract<T>, and writes the same contract headers.
If you only need headers and a plain response body, return a regular ASP.NET Core result:
app.MapGet("/catalog/prices/{id}", () =>
TypedResults.Ok(new Money
{
Amount = 149.99m,
Currency = "USD"
}))
.WithContract("catalog.prices", "1.2.0");
MVC / Controllers
For MVC controllers or actions, use the attribute:
[ApiController]
[Route("api/catalog/prices")]
[Contract("catalog.prices", "1.2.0")]
public sealed class CatalogController : ControllerBase
{
[HttpGet("{id}")]
public IResult GetPrice(string id)
{
var payload = new Money
{
Amount = 149.99m,
Currency = "USD"
};
return this.VersionedContract(payload);
}
}
The attribute declares endpoint metadata.
The middleware reads that metadata and writes the headers.
If you return this.VersionedContract(...), the body is wrapped into VersionedContract<T> using the same endpoint metadata.
If you return Ok(payload) or another normal controller result, the middleware still writes headers as long as the endpoint has [Contract(...)].
Declaring vs Writing
- declare the contract on the endpoint:
- Minimal API:
.WithContract(...) - MVC:
[Contract(...)]
- Minimal API:
- write contract headers:
app.UseRaycynixContracts()
- choose the response body format:
- plain DTO/body: return
Ok(...),TypedResults.Ok(...), etc. - versioned envelope: return
this.VersionedContract(...)orhttpContext.VersionedContract(...)
- plain DTO/body: return
Request Header Access
Read incoming contract metadata from request headers:
if (httpContext.TryGetRequestContractMetadata(out var requestContract))
{
// apply compatibility rules here
}
Validation Errors
Convert ASP.NET Core ModelState into the shared transport error shape:
var error = ModelState.ToErrorContract(traceId: HttpContext.TraceIdentifier);
This package intentionally provides transport integration only. It does not enforce compatibility policy or automatic contract negotiation.
Logging
The package uses the standard Microsoft.Extensions.Logging.ILogger<T> abstraction when a logger is available. Logger dependencies are optional, so the package can run without registering a logging provider. It does not require Raycynix.Extensions.Logging; any Microsoft-compatible logging provider can receive the events.
Contract metadata middleware and contract HTTP results write detailed execution diagnostics at Debug. They log contract names, versions, endpoint names, status codes, and envelope usage, but never log response payloads.
Enable Debug logs when troubleshooting contract header emission or contract result execution:
{
"Logging": {
"LogLevel": {
"Raycynix.Extensions.Contracts.AspNetCore": "Debug"
}
}
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. |
-
net10.0
- Raycynix.Extensions.Contracts (>= 2.2.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
v2.2.0 starts unified versioning for Raycynix packages and adds optional Microsoft.Extensions.Logging diagnostics for contract metadata middleware and contract HTTP results.