Rivet.Attributes
0.36.1
See the version list below for details.
dotnet add package Rivet.Attributes --version 0.36.1
NuGet\Install-Package Rivet.Attributes -Version 0.36.1
<PackageReference Include="Rivet.Attributes" Version="0.36.1" />
<PackageVersion Include="Rivet.Attributes" Version="0.36.1" />
<PackageReference Include="Rivet.Attributes" />
paket add Rivet.Attributes --version 0.36.1
#r "nuget: Rivet.Attributes, 0.36.1"
#:package Rivet.Attributes@0.36.1
#addin nuget:?package=Rivet.Attributes&version=0.36.1
#tool nuget:?package=Rivet.Attributes&version=0.36.1
<p align="center"> <h1 align="center">Rivet</h1> <p align="center"> <a href="https://www.nuget.org/packages/Rivet.Attributes"><img src="https://img.shields.io/nuget/v/Rivet.Attributes?label=Rivet.Attributes" alt="NuGet" /></a> <a href="https://www.nuget.org/packages/dotnet-rivet"><img src="https://img.shields.io/nuget/v/dotnet-rivet?label=dotnet-rivet" alt="NuGet" /></a> <img src="https://img.shields.io/badge/license-MIT-blue" alt="License" /> </p> </p>
Your C# is the contract. Rivet reads your compiled C# with Roslyn and emits an OpenAPI 3.1 spec — no runtime reflection, no attributes-on-everything, no drift between the code and the spec. The OpenAPI ecosystem does the rest: TypeScript types, a typed fetch client, Zod schemas, rendered docs.
oRPC gives you this when your server is TypeScript. Rivet gives you the same DX when your server is .NET.
dotnet add package Rivet.Attributes
dotnet tool install --global dotnet-rivet
Two ways in
Already have an ASP.NET API? Annotate it.
Mark the endpoints you want surfaced — the operation is derived from the real transport shape (routes, params, bodies, response types):
[ApiController]
[Route("api/tasks")]
public sealed class TasksController : ControllerBase
{
[RivetEndpoint]
[HttpGet("{id:guid}")]
[ProducesResponseType(typeof(TaskDetailDto), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(NotFoundDto), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Get(Guid id, CancellationToken ct) { ... }
}
That becomes GET /api/tasks/{id} with a typed 200 and 404 — route
constraints normalised, params classified, multipart and form bodies handled.
Starting fresh? Write the contract first.
A contract is plain C#: routes, inputs, outputs, and error responses in one place, as data:
[RivetContract]
public static class MembersContract
{
public static readonly RouteDefinition<PagedResult<MemberDto>> List =
Define.Get<PagedResult<MemberDto>>("/api/members");
public static readonly RouteDefinition<InviteMemberRequest, InviteMemberResponse> Invite =
Define.Post<InviteMemberRequest, InviteMemberResponse>("/api/members")
.Status(201)
.Returns<ValidationErrorDto>(422, "Validation failed")
.Secure("admin");
}
Handlers execute the contract, so the compiler enforces that your implementation matches the declaration — input type, output type, and (at runtime, on the typed-results path) status codes:
[HttpPost]
public async Task<IActionResult> Invite([FromBody] InviteMemberRequest request, CancellationToken ct)
=> (await MembersContract.Invite.Invoke(request, async req =>
{
// req is InviteMemberRequest; must return InviteMemberResponse — compiler-enforced
return new InviteMemberResponse(Guid.NewGuid());
})).ToActionResult();
Either way — annotated endpoints, contracts, or a mix — the spec comes out the same.
Generate
dotnet rivet --project path/to/Api.csproj --output ./generated
Writes ./generated/openapi.json, derived from the compiled C# via the Roslyn
semantic model. Value-object brands, generics, nullability, validation
attributes, polymorphic hierarchies (oneOf + discriminator), dictionary key
types, headers, descriptions, and examples all flow into the spec.
Consume
The spec plugs straight into the OpenAPI TypeScript ecosystem:
npx openapi-typescript ./generated/openapi.json -o ./src/api/schema.d.ts
npm install openapi-fetch
import createClient from "openapi-fetch";
import type { paths } from "./api/schema";
const api = createClient<paths>({ baseUrl: "https://api.example.com" });
// Path, params, body, and per-status responses all inferred.
const { data, error } = await api.GET("/api/tasks/{id}", {
params: { path: { id: taskId } },
});
if (error) {
// narrowed to NotFoundDto for the declared 404
console.error(error.message);
}
Docs via any OpenAPI renderer; runtime validators via openapi-zod-client if you want them.
Also in the box
- Contract coverage checking —
--checkverifies every contract field has an implementation on the declared route and method - OpenAPI import — one-shot onboarding for existing APIs: generate C# contracts from a spec, then the C# is the source of truth
- File endpoints, headers as contract concepts, minimal-API hosts, round-trippable specs
- Stable
RIVnnnndiagnostic IDs on every warning — grep or baseline by ID - A TypeScript-first sibling, rivet-ts — same pipeline, contracts authored as TS types, Hono runtime
Documentation
Getting Started · Contracts · CLI Reference · Type Mapping · Runtime Validation (the precise scope of what is and isn't enforced at runtime)
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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 is compatible. 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. |
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.46.0 | 255 | 10/3/2026 |
| 0.45.1 | 86 | 9/30/2026 |
| 0.45.0 | 115 | 9/29/2026 |
| 0.44.1 | 100 | 9/21/2026 |
| 0.44.0 | 95 | 9/19/2026 |
| 0.43.0 | 106 | 9/18/2026 |
| 0.42.0 | 95 | 9/17/2026 |
| 0.41.0 | 521 | 7/13/2026 |
| 0.40.0 | 140 | 7/11/2026 |
| 0.39.0 | 125 | 7/11/2026 |
| 0.38.0 | 123 | 6/13/2026 |
| 0.37.0 | 130 | 6/12/2026 |
| 0.36.1 | 126 | 6/12/2026 |
| 0.36.0 | 118 | 6/12/2026 |
| 0.35.0 | 117 | 6/12/2026 |
| 0.34.3 | 140 | 5/22/2026 |
| 0.34.2 | 122 | 5/11/2026 |
| 0.34.1 | 113 | 5/11/2026 |
| 0.34.0 | 116 | 4/21/2026 |
| 0.33.2 | 126 | 4/16/2026 |