From 996b217a23b167b81175d701971d53765eccb4ae Mon Sep 17 00:00:00 2001
From: Xavier <1859710+xavierjohn@users.noreply.github.com>
Date: Sat, 17 Oct 2026 09:25:38 -0700
Subject: [PATCH] Add AgentDocs guidance to the Asp.Versioning.Http package
Pack three Markdown guides for coding agents in Asp.Versioning.Http: a short
required guide for registration, endpoint versioning and default behavior,
and on-demand guides for version sources and defaults and for deprecation and
error responses.
The guides are packed by the build-only Trellis.AgentDocs.Packaging helper
(PrivateAssets="all"), which adds no dependency to the package. Consumers opt
in separately with the Trellis.AgentDocs tool, and a restored package is never
read until they approve it.
---
.../Asp.Versioning.Http.csproj | 15 ++++++
.../Asp.Versioning.Http/docs/agent-guide.md | 50 ++++++++++++++++++
.../docs/deprecation-and-errors.md | 36 +++++++++++++
.../docs/version-sources-and-defaults.md | 52 +++++++++++++++++++
4 files changed, 153 insertions(+)
create mode 100644 src/AspNetCore/WebApi/src/Asp.Versioning.Http/docs/agent-guide.md
create mode 100644 src/AspNetCore/WebApi/src/Asp.Versioning.Http/docs/deprecation-and-errors.md
create mode 100644 src/AspNetCore/WebApi/src/Asp.Versioning.Http/docs/version-sources-and-defaults.md
diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.Http/Asp.Versioning.Http.csproj b/src/AspNetCore/WebApi/src/Asp.Versioning.Http/Asp.Versioning.Http.csproj
index 4e32da2e..2b969895 100644
--- a/src/AspNetCore/WebApi/src/Asp.Versioning.Http/Asp.Versioning.Http.csproj
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.Http/Asp.Versioning.Http.csproj
@@ -15,6 +15,21 @@
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.Http/docs/agent-guide.md b/src/AspNetCore/WebApi/src/Asp.Versioning.Http/docs/agent-guide.md
new file mode 100644
index 00000000..2847cb5a
--- /dev/null
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.Http/docs/agent-guide.md
@@ -0,0 +1,50 @@
+# Asp.Versioning.Http
+
+`Asp.Versioning.Http` adds API versioning to ASP.NET Core **Minimal APIs**. Use
+`Asp.Versioning.Mvc` as well when the service has controllers.
+
+## Set up
+
+```csharp
+using Asp.Versioning;
+
+builder.Services.AddProblemDetails();
+builder.Services.AddApiVersioning( options => options.ReportApiVersions = true );
+```
+
+`ReportApiVersions = true` adds the `api-supported-versions` and `api-deprecated-versions`
+response headers. Without it, clients get no version information in responses.
+
+## Version the endpoints
+
+Create one versioned API from the app, then declare the versions each endpoint implements:
+
+```csharp
+var api = app.NewVersionedApi();
+
+api.MapGet( "/items", () => "version 1" ).HasApiVersion( 1.0 );
+api.MapGet( "/items", () => "version 2" ).HasApiVersion( 2.0 );
+
+// no version required
+api.MapGet( "/ping", () => "pong" ).IsApiVersionNeutral();
+```
+
+`MapGroup( ... ).HasApiVersion( ... )` on the object returned by `NewVersionedApi()` versions every
+endpoint in the group. A request is routed by the `api-version` query string parameter, for example
+`GET /items?api-version=2.0`.
+
+## Behavior you can rely on
+
+- A request with **no** version to a versioned endpoint fails with **400** (`unspecified`).
+- A version no endpoint supports fails with **400** (`unsupported`); a value that is not a version
+ (`api-version=banana`) fails with **400** (`invalid`). Both are `application/problem+json`.
+- `api-version=1` is read as `1.0`.
+- Call `NewVersionedApi()` on the app itself. Calling it on a `MapGroup` throws
+ `InvalidOperationException` ("A versioned API group cannot be mapped as a nested group.").
+
+## More
+
+- Change where clients send the version, or assume a default version:
+ [version sources and defaults](version-sources-and-defaults.md).
+- Deprecate a version or change error responses:
+ [deprecation and errors](deprecation-and-errors.md).
diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.Http/docs/deprecation-and-errors.md b/src/AspNetCore/WebApi/src/Asp.Versioning.Http/docs/deprecation-and-errors.md
new file mode 100644
index 00000000..6ede10d1
--- /dev/null
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.Http/docs/deprecation-and-errors.md
@@ -0,0 +1,36 @@
+# Deprecation and error responses
+
+## Deprecate a version
+
+Mark a version deprecated on the endpoints that still implement it:
+
+```csharp
+var api = app.NewVersionedApi();
+
+api.MapGet( "/old", () => "old" )
+ .HasDeprecatedApiVersion( 0.9 )
+ .HasApiVersion( 1.0 );
+```
+
+With `ReportApiVersions = true`, `GET /old?api-version=0.9` still succeeds and the response carries
+`api-supported-versions: 1.0, 2.0` and `api-deprecated-versions: 0.9`. The supported list covers all
+versions in the API, not only the ones on that endpoint.
+
+## Error responses
+
+All of these are `application/problem+json` with `status` 400 by default:
+
+| Request | `type` ends with |
+|---|---|
+| No version, no default assumed | `#unspecified` |
+| A version nothing implements, such as `api-version=3.0` | `#unsupported` |
+| A value that is not a version, such as `api-version=banana` | `#invalid` |
+
+Change the status for unsupported versions with `options.UnsupportedApiVersionStatusCode = 404;`;
+the response is still a `#unsupported` problem.
+
+## Version-neutral endpoints
+
+`IsApiVersionNeutral()` means no version is required: `GET /ping` and `GET /ping?api-version=1.0`
+both succeed. A neutral endpoint still rejects a version nothing in the API supports:
+`GET /ping?api-version=9.0` is a 400 `unsupported`.
diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.Http/docs/version-sources-and-defaults.md b/src/AspNetCore/WebApi/src/Asp.Versioning.Http/docs/version-sources-and-defaults.md
new file mode 100644
index 00000000..31833602
--- /dev/null
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.Http/docs/version-sources-and-defaults.md
@@ -0,0 +1,52 @@
+# Version sources and defaults
+
+## Where the version is read from
+
+The default reader accepts the version from the `api-version` **query string** parameter and from a
+**URL segment**. Setting `ApiVersionReader` **replaces** that default; it does not add to it.
+
+```csharp
+// header only: "?api-version=2.0" is now ignored and the request fails as unspecified
+builder.Services.AddApiVersioning( options =>
+ options.ApiVersionReader = new HeaderApiVersionReader( "x-api-version" ) );
+```
+
+To accept several sources, combine them explicitly:
+
+```csharp
+builder.Services.AddApiVersioning( options =>
+ options.ApiVersionReader = ApiVersionReader.Combine(
+ new QueryStringApiVersionReader( "v" ),
+ new HeaderApiVersionReader( "x-api-version" ) ) );
+```
+
+With the combined reader above, `?v=1.0` and `x-api-version: 2.0` both work, and the default
+`api-version` parameter no longer does.
+
+## URL segment versioning
+
+Put the `apiVersion` route constraint in the route template:
+
+```csharp
+var api = app.NewVersionedApi();
+api.MapGet( "/v{version:apiVersion}/seg", () => "seg" ).HasApiVersion( 1.0 );
+```
+
+`GET /v1/seg` and `GET /v1.0/seg` succeed. A version no endpoint supports (`/v2/seg`) does **not**
+produce the 400 `unsupported` problem: the route no longer matches and the response is **404**. A
+request to `/seg?api-version=1.0` is also 404, because the template requires the segment.
+
+## When the client sends no version
+
+By default an unspecified version fails with 400. To serve a default version instead:
+
+```csharp
+builder.Services.AddApiVersioning( options =>
+{
+ options.AssumeDefaultVersionWhenUnspecified = true;
+ options.DefaultApiVersion = new ApiVersion( 2, 0 ); // optional; the default is 1.0
+} );
+```
+
+Assuming a default hides a missing version from clients, so only enable it for services that already had
+unversioned clients.