Skip to content

OpenApi: Lowercase document name on registration to match AddOpenApi internal behaviour (closes #23210)#23212

Merged
kjac merged 2 commits into
mainfrom
v18/bugfix/lowercase-openapi-document-name
Jun 26, 2026
Merged

OpenApi: Lowercase document name on registration to match AddOpenApi internal behaviour (closes #23210)#23212
kjac merged 2 commits into
mainfrom
v18/bugfix/lowercase-openapi-document-name

Conversation

@lauraneto

@lauraneto lauraneto commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Prerequisites

  • I have added steps to test this contribution in the description below

If there's an existing issue for this PR then this fixes #23210

Description

AddOpenApi (from Microsoft.AspNetCore.OpenApi) lowercases the document name internally when registering its keyed services. ReplaceOpenApiSchemaService then searches for the keyed OpenApiSchemaService registration using the name as passed — so if the name contains uppercase letters the lookup fails with an InvalidOperationException.

Both BackOfficeOpenApiDocumentBuilder.Build() and AddUmbracoOpenApiDocument now normalise the name to lowercase for DI registration calls (AddOpenApi, AddOpenApiDocumentToUi, ReplaceOpenApiSchemaService). The original name is preserved where it is used for endpoint filtering — HasMapToApiAttribute in BackOfficeOpenApiDocumentBuilder and ApiName in ConfigureUmbracoOpenApiOptionsBase subclasses — so [MapToApi] attribute matching continues to work correctly.

Testing

Add a sample constants file:

internal static class ExampleApiConstants
{
    // Mixed-case name intentionally used to exercise the AddOpenApi lowercasing behaviour.
    internal const string ApiName = "MyExtensionApi";
}

Add a sample controller:

[ApiController]
[ApiVersion("1.0")]
[BackOfficeRoute("example/api/v{version:apiVersion}")]
[MapToApi(ExampleApiConstants.ApiName)]
public class ExampleApiController : ControllerBase
{
    [HttpGet("ping")]
    [ProducesResponseType<string>(StatusCodes.Status200OK)]
    public string Ping() => "Pong";
}

Add a sample composer registering :

public class ExampleApiComposer : IComposer
{
    public void Compose(IUmbracoBuilder builder) =>
        builder.AddBackOfficeOpenApiDocument(
            ExampleApiConstants.ApiName,
            document => document
                .WithTitle("Example API")
                .WithJsonOptions(Umbraco.Cms.Core.Constants.JsonOptionsNames.BackOffice));
}

Start the application. Before this fix it throws InvalidOperationException at startup. After the fix the application starts and the document is available at /umbraco/openapi/mydocument.json.
Also verify that the Management and DeliveryAPI open api documents are still accessible and including the respective endpoints.

@lauraneto lauraneto changed the title OpenApi: Lowercase document name on registration to match AddOpenApi internal behaviour OpenApi: Lowercase document name on registration to match AddOpenApi internal behaviour (closes #23210) Jun 26, 2026
@lauraneto lauraneto marked this pull request as ready for review June 26, 2026 09:37
Copilot AI review requested due to automatic review settings June 26, 2026 09:37
@claude

claude Bot commented Jun 26, 2026

Copy link
Copy Markdown

Claude finished @lauraneto's task in 4m 8s —— View job


PR Review

Target: origin/main · Based on commit: b894f500

Normalises the OpenAPI document name to lowercase before all DI registration calls (AddOpenApi, AddOpenApiDocumentToUi, ReplaceOpenApiSchemaService), matching the internal behaviour of Microsoft.AspNetCore.OpenApi which lowercases the name when keying its services. The original mixed-case name is preserved solely for [MapToApi] attribute matching in ShouldInclude.


Important

  • src/Umbraco.Cms.Api.Common/OpenApi/BackOfficeOpenApiDocumentBuilder.cs:120: No regression test covers the specific bug scenario — a mixed-case document name combined with WithJsonOptions causing startup to throw InvalidOperationException. The existing integration tests (BackOfficeOpenApiDocumentWithJsonOptionsTests) use "test-with-json-options" (already lowercase) and would pass both before and after the fix, proving nothing about the case-sensitivity issue. Per the repo testing policy, a bug-fix test must fail without the fix. Adding a subclass with ApiName = "TestWithJsonOptions" (mixed-case) would create an honest regression guard. Fix this →

Approved with Suggestions for improvement

The fix is correct and minimal — the split between registrationName (lowercase, for DI) and DocumentName (original case, for [MapToApi] matching) is exactly the right approach, and the comment in Build() explains the non-obvious constraint well. The same pattern is consistently applied in AddUmbracoOpenApiDocument. Good to go, but please consider adding the missing regression test before merging.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a startup failure when registering OpenAPI documents with mixed-case names by normalizing the document name to lowercase for DI registration, aligning Umbraco’s registrations with Microsoft.AspNetCore.OpenApi’s internal lowercasing behavior.

Changes:

  • Normalize BackOfficeOpenApiDocumentBuilder’s DI registration key to DocumentName.ToLowerInvariant() while preserving the original DocumentName for [MapToApi] endpoint filtering.
  • Normalize AddUmbracoOpenApiDocument’s apiName to lowercase before calling AddOpenApi, UI registration, and schema-service replacement.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/Umbraco.Cms.Api.Common/OpenApi/BackOfficeOpenApiDocumentBuilder.cs Lowercases the OpenAPI document registration key to keep AddOpenApi, UI registration, and schema-service replacement keyed consistently.
src/Umbraco.Cms.Api.Common/DependencyInjection/UmbracoBuilderApiExtensions.cs Lowercases apiName before OpenAPI registration to match keyed service behavior.

Comment thread src/Umbraco.Cms.Api.Common/OpenApi/BackOfficeOpenApiDocumentBuilder.cs Outdated
Comment thread src/Umbraco.Cms.Api.Common/OpenApi/BackOfficeOpenApiDocumentBuilder.cs Outdated
@claude claude Bot added the area/backend label Jun 26, 2026
…nternal behaviour

AddOpenApi lowercases the document name when registering its keyed services, so
ReplaceOpenApiSchemaService must receive the same lowercased key or the lookup
throws. BackOfficeOpenApiDocumentBuilder now computes a normalised registration
name and uses it for all DI calls, while keeping DocumentName in its original
casing. ShouldInclude matches [MapToApi] case-insensitively to align with how
documents are registered, and the UI dropdown label falls back to DocumentName
(original casing) rather than the lowercased registration key.
AddUmbracoOpenApiDocument applies the same normalisation for its apiName parameter.
@lauraneto lauraneto force-pushed the v18/bugfix/lowercase-openapi-document-name branch from b894f50 to 293bb7d Compare June 26, 2026 10:15
Covers the bug scenario where AddBackOfficeOpenApiDocument with a mixed-case
name and WithJsonOptions threw InvalidOperationException at startup, and verifies
that ShouldInclude matches [MapToApi] case-insensitively.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

@sonarqubecloud

Copy link
Copy Markdown

@kjac kjac left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works like a charm, and I can reproduce the issue on main 👍

@kjac kjac merged commit df16c11 into main Jun 26, 2026
31 checks passed
@kjac kjac deleted the v18/bugfix/lowercase-openapi-document-name branch June 26, 2026 11:59
pull Bot pushed a commit to steelburn/Umbraco-CMS that referenced this pull request Jul 1, 2026
…internal behaviour (closes umbraco#23210) (umbraco#23212)

* Lowercase OpenAPI document name on registration to match AddOpenApi internal behaviour

AddOpenApi lowercases the document name when registering its keyed services, so
ReplaceOpenApiSchemaService must receive the same lowercased key or the lookup
throws. BackOfficeOpenApiDocumentBuilder now computes a normalised registration
name and uses it for all DI calls, while keeping DocumentName in its original
casing. ShouldInclude matches [MapToApi] case-insensitively to align with how
documents are registered, and the UI dropdown label falls back to DocumentName
(original casing) rather than the lowercased registration key.
AddUmbracoOpenApiDocument applies the same normalisation for its apiName parameter.

* Add regression tests for mixed-case OpenAPI document name registration

Covers the bug scenario where AddBackOfficeOpenApiDocument with a mixed-case
name and WithJsonOptions threw InvalidOperationException at startup, and verifies
that ShouldInclude matches [MapToApi] case-insensitively.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OpenApi: AddBackOfficeOpenApiDocument throws when document name contains uppercase letters

4 participants