Rivet.Attributes
0.35.0
See the version list below for details.
dotnet add package Rivet.Attributes --version 0.35.0
NuGet\Install-Package Rivet.Attributes -Version 0.35.0
<PackageReference Include="Rivet.Attributes" Version="0.35.0" />
<PackageVersion Include="Rivet.Attributes" Version="0.35.0" />
<PackageReference Include="Rivet.Attributes" />
paket add Rivet.Attributes --version 0.35.0
#r "nuget: Rivet.Attributes, 0.35.0"
#:package Rivet.Attributes@0.35.0
#addin nuget:?package=Rivet.Attributes&version=0.35.0
#tool nuget:?package=Rivet.Attributes&version=0.35.0
<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 C# types and ASP.NET endpoints with Roslyn and emits an OpenAPI 3.1 specification — no attributes-on-everything, no runtime reflection, no drift between your declared C# types and what the spec says.
Rivet maps what actually survives the wire boundary. The OpenAPI ecosystem does the rest: TypeScript types via openapi-typescript, a typed client via openapi-fetch, Zod schemas via openapi-zod-client, docs via any OpenAPI renderer.
oRPC gives you this when your server is TypeScript. Rivet gives you the same DX when your server is .NET.
Install
dotnet add package Rivet.Attributes
dotnet tool install --global dotnet-rivet
Generate
dotnet rivet --project path/to/Api.csproj --output ./generated
This writes ./generated/openapi.json — an OpenAPI 3.1 spec derived from your compiled
C# (Roslyn semantic model, not runtime reflection). Omit --output to preview the spec
on stdout. --title, --version, and --server set the spec's info and servers
metadata (CLI reference).
C# Types → OpenAPI Schemas
public enum WorkItemStatus { Draft, Open, InProgress, Review, Done, Cancelled }
public sealed record Email(string Value);
public sealed record MemberDto(Guid Id, string Name, Email Email, string Role);
// components/schemas (excerpt)
{
"WorkItemStatus": {
"type": "string",
"enum": ["draft", "open", "inProgress", "review", "done", "cancelled"]
},
"Email": { "type": "string", "x-rivet-brand": "Email" },
"MemberDto": {
"type": "object",
"properties": {
"id": { "type": "string", "format": "uuid" },
"name": { "type": "string" },
"email": { "$ref": "#/components/schemas/Email" },
"role": { "type": "string" }
},
"required": ["id", "name", "email", "role"]
}
}
Value-object brands, generics (monomorphised), nullability, validation attributes
([Range], [StringLength], [RegularExpression], ...), descriptions, and examples all
flow into the spec. So do [JsonPolymorphic]/[JsonDerivedType] hierarchies
(oneOf + discriminator) and dictionary key types (propertyNames for enum, branded,
and primitive keys) — plus x-rivet-* vendor extensions that preserve C#-level fidelity
(brands, generics, contract names) through the spec
(vendor extensions reference,
type mapping).
ASP.NET Endpoints → OpenAPI Operations
Rivet works with ordinary ASP.NET controllers. Mark the endpoints you want surfaced and the operation is derived from the real transport shape:
[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)
{
return Ok(default(TaskDetailDto));
}
}
becomes GET /api/tasks/{id} with a typed 200 (TaskDetailDto) and 404 (NotFoundDto)
response — route constraints normalised, params classified
(route/query/header/body/form/file — [FromHeader] maps to in: header),
multipart and form-encoded bodies handled.
Consume the Spec (TypeScript)
The generated 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" });
// Fully type-safe: path, params, body, and per-status responses all inferred.
const { data, error, response } = await api.GET("/api/tasks/{id}", {
params: { path: { id: taskId } },
});
if (error) {
// narrowed to NotFoundDto for the declared 404
console.error(error.message);
}
Want runtime validation? Generate Zod schemas from the same spec with openapi-zod-client.
Advanced Features
Rivet also supports:
- contract-driven APIs with
[RivetContract]— compiler-enforced single source of truth for routes, inputs, outputs, and error responses, with runtimeInvokehelpers and coverage checking - minimal API hosts
- file endpoints with query-string auth (file uploads & downloads)
- headers as contract concepts —
[RivetHeader]/[FromHeader]request headers and.WithResponseHeader(...)response headers (attributes, route definition API) - stable
RIVnnnndiagnostic IDs on every warning — grep or baseline by ID (diagnostics reference) - OpenAPI import — a one-shot onboarding scaffold for existing APIs: it generates C# contracts once, with loud diagnostics for anything it can't represent (supported profile); the C# then becomes the source of truth
- round-trips: emit → import → emit produces an equivalent spec (security scheme definitions come from
--security, not the original spec) - the TypeScript-first sibling project rivet-ts (Hono runtime + the same OpenAPI pipeline via the bundled Rivet binary)
What Rivet Enforces (and What It Doesn't)
Rivet's guarantees are spec-time, not runtime. The C# compiler enforces handler
input/output types on .Invoke(), and contract Invoke validates that returned
status codes (and, for ASP.NET typed results, the payload's C# type) match the
declaration. Rivet does not validate request or response data at runtime:
- constraint attributes (
[Range],[StringLength], ...) flow into the spec but are not checked by Rivet at runtime — enforcement is the host framework's job, and the docs have the recipes ([ApiController]model validation on controller hosts,Validator.TryValidateObjecton minimal-API hosts;[RivetConstraints]is aValidationAttributeand participates in both) - response bodies are not shape-checked — extra properties on a returned object serialize to the wire
- declared request/response headers are spec-only — Rivet never binds, sets, or validates them
Define.Fileendpoints have no runtime enforcement at all
Full statement: Runtime Validation.
Documentation
Start with:
- Getting Started
- CLI Reference
- OpenAPI Emission
- Contracts
- OpenAPI Import (onboarding scaffold) and the Import Profile
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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 was computed. 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. |
-
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 | 256 | 10/3/2026 |
| 0.45.1 | 86 | 9/30/2026 |
| 0.45.0 | 116 | 9/29/2026 |
| 0.44.1 | 101 | 9/21/2026 |
| 0.44.0 | 95 | 9/19/2026 |
| 0.43.0 | 107 | 9/18/2026 |
| 0.42.0 | 96 | 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 |