Skip to content

v11 update: OpenAPI 3.2.0 support (Microsoft.OpenApi 3.x breaking change) #37706

Closed

Description

@wadepickett

Note

This is an AI-assisted coverage analysis created by wadepickett.

Target repository: dotnet/AspNetCore.Docs
Analyzed at commit: 4986136881f2bbf1879f10106467769df5a49932
Product source verified at: dotnet/aspnetcore @ 1fcd7ef305697a1888f3ede076010350ae9f4f8d
Source release note: OpenAPI 3.2.0 support (Breaking Change)

Important

customize-openapi.md is split by three separate .NET 11 issues. The article body is a single :::moniker range=">= aspnetcore-10.0" zone (L13 → L233), and three issues each need an independent State D split inside it:

Issue Insertion point Subject
This issue L30 Microsoft.OpenApi 3.x upgrade warning for transformer authors
#37705 L108 [Obsolete] replaces the manual deprecation transformer
#37703 L202 Array schema reference IDs

The splits don't overlap textually and can be applied in any order, but each issue's stated moniker balance assumes it is the only one applied. The zone count goes 1 / 1 → 3 / 3 → 5 / 5 → 7 / 7 once all three land. Apply them bottom-up (L202, then L108, then L30) so earlier line numbers stay valid, and re-derive the enclosing zone before each.


🎯 Goal

The feature itself is documented and so is the breaking change. The problem is that nothing connects them to the article where the break is felt.

Both halves of this release note already have homes:

What's missing is the link between them. A repository-wide search of aspnetcore/fundamentals/openapi/ for any reference to a breaking-changes/11/ article returns zero results. The only breaking-change link anywhere in that folder is to a .NET 10 analyzers change at include-metadata.md L468.

That matters because of who this break hits. Per the breaking-change article: "Transformer code that does anything more than read-only inspection—sets extension values, walks nested schemas, or constructs new schemas—usually needs to be updated." The reader whose AddSchemaTransformer call stopped compiling opens Customize OpenAPI documents — the transformers article — not a breaking-changes index they've never browsed. That article says nothing about the upgrade.

A second, smaller problem: the breaking-change article pins a specific patch version that has already gone stale.


✅ Coverage status summary

Legend: ✅ already documented · ✏️ update needed · 🟣 could not determine

# Feature element from What's New Status Where
1 Microsoft.AspNetCore.OpenApi supports generating OpenAPI 3.2.0 documents ✅ aspnetcore-openapi.md L17
2 The support comes via an updated dependency on Microsoft.OpenApi 3.x ✅ breaking-changes/11/microsoft-openapi-3x.md L9
3 The update includes breaking changes from the underlying library ✅ microsoft-openapi-3x.md L37–L46
4 Breaking change is listed in the .NET 11 breaking-changes index ✅ breaking-changes/11/overview.md L24
5 Which transformer interfaces are affected ✅ microsoft-openapi-3x.md L67–L72
6 Set options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_2 when calling AddOpenApi ✅ aspnetcore-openapi.md L25–L34
7 No article under fundamentals/openapi/ links to the Microsoft.OpenApi 3.x breaking change — including the transformers article, where the break is actually felt ✏️ 1. Update — fundamentals/openapi/customize-openapi.md L25–L31
8 The breaking-change article pins "currently 3.6.0"; the product's version range has since moved, and the article doesn't link the canonical upgrade guide the release note points at ✏️ 2. Update — breaking-changes/11/microsoft-openapi-3x.md L9 and L65
9 "Subsequent updates take advantage of new capabilities in the 3.2.0 specification, such as item schema support for streaming events" 🟣 Forward reference to Server-Sent Events itemSchema support. Owned by #37704, where it's a confirmed gap. Not addressed here.

🔢 Version applicability

Applies to: >= aspnetcore-11.0
Target moniker: >= aspnetcore-11.0
Earlier versions affected: None. .NET 10 and earlier depend on Microsoft.OpenApi 2.x and must not see this content.

Article monikerRange Moniker state
aspnetcore/fundamentals/openapi/customize-openapi.md '>= aspnetcore-9.0' State D — insertion sits inside a broader zone. The article body has exactly one zone: :::moniker range=">= aspnetcore-10.0" opens at L13 and :::moniker-end closes at L233. The insertion point at L30 is inside it, and >= aspnetcore-10.0 is broader than the target >= aspnetcore-11.0. The full four-directive split is required.
aspnetcore/breaking-changes/11/microsoft-openapi-3x.md (none) State A — no moniker zones. Verified: the file contains 0 :::moniker range= and 0 :::moniker-end directives, and 0 tab-group markers. Breaking-change articles are version-scoped by folder (breaking-changes/11/), not by moniker. Edit the prose directly; adding a zone here would be wrong.

Tab groups: Neither insertion point is inside a # [Tab](#tab/...) group. customize-openapi.md contains no tab groups at all.


📋 Coverage gap summary

The Microsoft.OpenApi 2.x → 3.x bump is a source-incompatible change that breaks exactly one kind of code: OpenAPI transformers. ASP.NET Core has a whole article about writing those — Customize OpenAPI documents — and it was written against the 2.x object model. It registers document, operation, and schema transformers, walks schemas, and sets extension values. It never mentions that in .NET 11 the types those transformers receive changed shape.

A developer upgrading to .NET 11 gets a compile error on new OpenApiString(...) and goes straight to the transformers article for the fix. It isn't there. The fix is one folder away in a breaking-changes article they have no reason to guess exists, and nothing in the OpenAPI documentation set points at it.

Separately, the breaking-change article states the dependency is "Microsoft.OpenApi 3.x (currently 3.6.0)." At the pinned product commit, eng/Versions.props declares <MicrosoftOpenApiVersion>[3.10.2,4.0.0)</MicrosoftOpenApiVersion>. Pinning a patch version in prose guarantees the article goes stale between servicing releases; the major version is the durable fact and is already in the title.

Feature announced in What's New:

Microsoft.AspNetCore.OpenApi now supports OpenAPI 3.2.0 through an updated dependency on Microsoft.OpenApi 3.3.1. This update includes breaking changes from the underlying library. For more information, see the Microsoft.OpenApi upgrade guide.

Breaking change: Yes — source incompatible, and binary incompatible for libraries compiled against Microsoft.OpenApi 2.x. Already correctly classified in the existing breaking-change article.

Note on the version number in the release note. The release note says the dependency is Microsoft.OpenApi 3.3.1. The breaking-change article says 3.6.0. Product source at the pinned commit says [3.10.2,4.0.0). Three different numbers in three places. The release-note figure is a separate problem and is deliberately not treated as a docset coverage gap here. Change 2 below fixes only the docset half.


📁 Affected files

Item Path Lines Section
1. aspnetcore/fundamentals/openapi/customize-openapi.md 25–31 "OpenAPI document transformers"
2. aspnetcore/breaking-changes/11/microsoft-openapi-3x.md 9, 65 Intro; "Recommended action"

Target article uids: fundamentals/openapi/customize-openapi (the breaking-change article has no uid; link it by site-relative path, as include-metadata.md L468 already does for the .NET 10 analyzers change)


📝 Proposed changes

✏️ 1. Update — aspnetcore/fundamentals/openapi/customize-openapi.md, insert after line 30

Applies to: >= aspnetcore-11.0
Moniker handling: State D — full four-directive split required. The insertion point is inside :::moniker range=">= aspnetcore-10.0" (opens L13, closes L233), which is broader than the target. The edit must close that zone, open >= aspnetcore-11.0, add the content, close it, and reopen >= aspnetcore-10.0 with the range expression reproduced character for character, including the double quotes and the space after range=.
Moniker balance: currently 1 :::moniker range= and 1 :::moniker-end. After this edit alone: 3 and 3. See the callout at the top of this issue — two other issues split the same zone, and all three together produce 7 / 7.
Location: Line 30, between the three-category transformer list and the paragraph that begins "Transformers can be registered onto the document".

Before (lines 25–31):

Transformers fall into three categories:

* Document transformers have access to the entire OpenAPI document. These can be used to make global modifications to the document.
* Operation transformers apply to each individual operation. Each individual operation is a combination of path and HTTP method. These can be used to modify parameters or responses on endpoints.
* Schema transformers apply to each schema in the document. These can be used to modify the schema of request or response bodies, or any nested schemas.

Transformers can be registered onto the document by calling the <xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions.AddDocumentTransformer%2A> method on the <xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions> object. The following snippet shows different ways to register transformers onto the document:

After:

Transformers fall into three categories:

* Document transformers have access to the entire OpenAPI document. These can be used to make global modifications to the document.
* Operation transformers apply to each individual operation. Each individual operation is a combination of path and HTTP method. These can be used to modify parameters or responses on endpoints.
* Schema transformers apply to each schema in the document. These can be used to modify the schema of request or response bodies, or any nested schemas.

:::moniker-end

:::moniker range=">= aspnetcore-11.0"

> [!IMPORTANT]
> .NET 11 upgrades `Microsoft.AspNetCore.OpenApi` from `Microsoft.OpenApi` 2.x to 3.x. The transformer interfaces are unchanged, but the shape of the `OpenApiDocument`, `OpenApiOperation`, and `OpenApiSchema` objects they receive has changed. Transformer code that sets extension values, walks nested schemas, or constructs new schemas usually needs to be updated. For migration guidance, see [Microsoft.OpenApi upgraded to 3.x](/aspnet/core/breaking-changes/11/microsoft-openapi-3x).

:::moniker-end

:::moniker range=">= aspnetcore-10.0"

Transformers can be registered onto the document by calling the <xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions.AddDocumentTransformer%2A> method on the <xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions> object. The following snippet shows different ways to register transformers onto the document:

Rationale: This is the article the reader is already in when the question occurs to them. It's placed after the definition of the three transformer categories — so the reader knows what a transformer is before being told theirs may not compile — and before the registration walkthrough, so they see the warning before copying any sample. It's a pointer, not a duplicate: all the migration detail stays in the breaking-change article, which is the right owner and is already thorough.

⚠️ Don't take the article's >= aspnetcore-9.0 front matter as license to insert directly. Front-matter monikerRange gates which versions render the article at all; it says nothing about which zone an insertion point falls in. The enclosing zone here is >= aspnetcore-10.0, and .NET 10 readers must not see a .NET 11 upgrade warning.


✏️ 2. Update — aspnetcore/breaking-changes/11/microsoft-openapi-3x.md, replace line 9 and line 65

Applies to: the whole article (version-scoped by its breaking-changes/11/ folder)
Moniker handling: State A — no zones exist and none should be added. The file has 0 moniker directives and 0 tab groups. Moniker balance is 0/0 before and 0/0 after.
Location: Line 9 (opening paragraph) and line 65 (last line of "Recommended action").

Before (line 9):

`Microsoft.AspNetCore.OpenApi` in ASP.NET Core 11 takes a dependency on `Microsoft.OpenApi` 3.x (currently 3.6.0). The previous release (.NET 10) depended on `Microsoft.OpenApi` 2.x. This is a major-version bump of a transitive dependency, and several types that document and operation transformers receive have changed shape.

After (line 9):

`Microsoft.AspNetCore.OpenApi` in ASP.NET Core 11 takes a dependency on `Microsoft.OpenApi` 3.x. The previous release (.NET 10) depended on `Microsoft.OpenApi` 2.x. This is a major-version bump of a transitive dependency, and several types that document and operation transformers receive have changed shape.

Before (line 65):

For the canonical migration notes for the 3.0, 3.1, 3.2, and later releases, see the [OpenAPI.NET release notes](https://github.com/microsoft/OpenAPI.NET/releases).

After (line 65):

For step-by-step migration instructions, see the [Microsoft.OpenApi 3.x upgrade guide](https://github.com/microsoft/OpenAPI.NET/blob/main/docs/upgrade-guide-3.md). For the per-release notes covering the 3.0, 3.1, 3.2, and later releases, see the [OpenAPI.NET release notes](https://github.com/microsoft/OpenAPI.NET/releases).

Rationale: Dropping "(currently 3.6.0)" removes the only part of the sentence guaranteed to rot — the patch version moves with every servicing release, and at the pinned product commit the declared range is already [3.10.2,4.0.0). The major version, which is the fact readers act on, survives in the title and in the remaining sentence. The line 65 change adds the upgrade guide the release note itself links to; it's the actionable migration document, while the releases page is a changelog.


✅ 3. Update — TOC

No TOC change required. Both articles already have entries: customize-openapi.md under Fundamentals > OpenAPI, and microsoft-openapi-3x.md in the .NET 11 breaking-changes index at overview.md L24.


✅ Action plan

  1. Read breaking-changes/11/microsoft-openapi-3x.md end to end and confirm rows 2–5. It is comprehensive; resist the urge to restate any of it in customize-openapi.md.
  2. Apply change 2 first. It's two single-line prose replacements in an article with no moniker zones and no tab groups — the lowest-risk edit in this issue.
  3. Check whether #37705 (L108) or #37703 (L202) has already split customize-openapi.md. If so, re-derive the enclosing zone of L30 and the expected balance from the current file rather than trusting the figures below.
  4. Apply change 1. Copy :::moniker range=">= aspnetcore-10.0" from L13 verbatim when reopening the zone. A reopened range that differs by even a space silently drops the rest of the article from the .NET 10 build.
  5. Verify zone balance in customize-openapi.md: 3 :::moniker range= and 3 :::moniker-end after this edit alone, up from 1 and 1 — or 5 / 5 or 7 / 7 if the other issues have landed.
  6. Build with the .NET 10 moniker and confirm everything from the transformer-registration paragraph to the end of the article still renders. This is the specific failure a mismatched reopened range produces.
  7. Build with the .NET 11 moniker and confirm the new IMPORTANT note renders exactly once.
  8. Verify the site-relative link /aspnet/core/breaking-changes/11/microsoft-openapi-3x resolves. The breaking-change article has no uid, so it can't be referenced with <xref:>; include-metadata.md L468 establishes the site-relative pattern for this docset.
  9. Verify the external link https://github.com/microsoft/OpenAPI.NET/blob/main/docs/upgrade-guide-3.md resolves (confirmed HTTP 200 at analysis time).
  10. Resolve any OpenPublishing.Build warnings.

⚠️ Review considerations

  • Row 9 is deliberately left at 🟣 here. The release note's closing sentence — "Subsequent updates take advantage of new capabilities in the 3.2.0 specification, such as item schema support for streaming events" — is a forward reference to the Server-Sent Events itemSchema work, which is its own release-note section. It's a confirmed docset gap, but #37704 owns it. Fixing it here would put streaming-events content in the transformers article, which is the wrong place.
  • Overlap with #37701. The release note tells readers to set options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_2 to get a 3.2 document. A later change in the same release made 3.2 the default, so that instruction is no longer necessary. aspnetcore-openapi.md L25 already states the default correctly, so the docset is right where the release note is misleading. v11 update: OpenAPI document generation — HTTP QUERY support and the default 3.2 document version #37701 covers the default-version story and the one remaining stale spot at L117–L126. Don't duplicate that here.
  • Should the pointer also go in aspnetcore-openapi.md? Considered and not proposed. That article is the OpenAPI overview; the break is specific to transformer authors, and a second copy of the warning in the overview would dilute it and add a second State D split for marginal benefit. If a reviewer wants broader signposting, the cheaper option is a line in the breaking-changes index rather than another zone split.
  • Change 2 touches a breaking-change article, not a fundamentals/ article. That's intentional and in scope: breaking-changes/11/ is evergreen reference content, not release notes, so it's a legitimate edit target. aspnetcore/release-notes/** is not, and nothing here proposes an edit there.
  • Out of scope for this issue: the Microsoft.OpenApi version number in the release note (a release-note problem, not a docset gap); OpenAPI 3.2 becoming the default (#37701); Server-Sent Events item schemas (#37704).

🔗 References

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions