Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 13, 2025

  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Fix case-insensitive comparison for endpoint group names

Description

OpenAPI document filtering excluded endpoints when .WithGroupName() casing differed from .AddOpenApi() document name. Since document names are lowercased but endpoint metadata preserves original casing, case-sensitive comparison caused exclusion.

// This now works - endpoints appear in the document
builder.Services.AddOpenApi("FirstGroup");  // Stored as "firstgroup"
app.MapGet("/api/todos", () => { })
    .WithGroupName("FirstGroup");  // Previously excluded, now included

Changes:

  • Modified ShouldInclude predicate in OpenApiOptions to use StringComparison.OrdinalIgnoreCase
  • Added test verifying case-insensitive matching behavior

Fixes #64335

Original prompt

This section details on the original issue you should resolve

<issue_title>OpenAPI Generation No Longer Groups Endpoints Using WithGroupName</issue_title>
<issue_description>### Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

In .NET 9, multiple Open API spec docs could be generated with a specific name utilizing the .WithGroupName extension method on either the group itself or particular endpoints. This allowed for a name other than the group's prefix to be used for grouping endpoints into an OpenAPI document that utilized a name other than the group's route prefix.

Now, it seems that the OpenAPI generator does not group those endpoints into the related spec document and instead excludes them entirely.

Expected Behavior

I should be able to group endpoints in an OpenAPI Spec document named something other than the Group prefix, utilizing .WithGroupName("MyGroupName") and .AddOpenApi("MyGroupName").

Steps To Reproduce

I have a minimal repro solution that demonstrates the behaviors here:
https://github.com/GoValidate/AspNetCore-Net10-OpenApi-Repro

The OpenApiNet9 and OpenApiNet10 are carbon copies of each other, with one targeting .NET 9 (and the .NET 9 version of AspNetCore OpenAPI) and the other targeting .NET 10 (and the .NET 10 version of AspNetCore OpenAPI). The code in both cases is the same:

var builder = WebApplication.CreateBuilder();

const string FirstGroup = "FirstGroup";
const string SecondGroup = "SecondGroup";

builder.Services.AddOpenApi();
builder.Services.AddOpenApi(FirstGroup);
builder.Services.AddOpenApi(SecondGroup);

var app = builder.Build();

app.MapOpenApi();

app.Map("no-group", () => "No group endpoint");
app.MapGroup("/first-group")
    .MapGet("/explicit", () => $".WithGroup(\"{FirstGroup}\") called on this endpoint")
    .WithGroupName(FirstGroup);

app.MapGroup("/second-group")
    .WithGroupName("SecondGroup")
    .MapGet("/implicit", () => $".WithGroup(\"{SecondGroup}\") called on the parent group");

app.Run();

New NET 10 Behavior

The following Open API docs are generated in NET 10:
https://localhost:5001/openapi/FirstGroup.json

{
  "openapi": "3.1.1",
  "info": {
    "title": "OpenApiNet10 | firstgroup",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://localhost:5001/"
    }
  ],
  "paths": { }
}

https://localhost:5001/openapi/SecondGroup.json

{
  "openapi": "3.1.1",
  "info": {
    "title": "OpenApiNet10 | secondgroup",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://localhost:5001/"
    }
  ],
  "paths": { }
}

Expected Behavior

In OpenApiNet9, the following swagger docs are generated:

https://localhost:7001/openapi/FirstGroup.json

{
  "openapi": "3.0.1",
  "info": {
    "title": "OpenApiNet9 | FirstGroup",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://localhost:7001/"
    }
  ],
  "paths": {
    "/first-group/explicit": {
      "get": {
        "tags": [
          "OpenApiNet9"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": { },
  "tags": [
    {
      "name": "OpenApiNet9"
    }
  ]
}

https://localhost:7001/openapi/SecondGroup.json

{
  "openapi": "3.0.1",
  "info": {
    "title": "OpenApiNet9 | SecondGroup",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://localhost:7001/"
    }
  ],
  "paths": {
    "/second-group/implicit": {
      "get": {
        "tags": [
          "OpenApiNet9"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": { },
  "tags": [
    {
      "name": "OpenApiNet9"
    }
  ]
}

Exceptions (if any)

No response

.NET Version

10.0.100

Anything else?

IDE is Rider (though this exhibits with dotnet run).

Output from dotnet --info

.NET SDK:
 Version:           10.0.100
 Commit:            b0f34d51fc
 Workload version:  10.0.100-manifests.4c0ca8ba
 MSBuild version:   18.0.2+b0f34d51f

Runtime Environment:
 OS Name:     Mac OS X
 OS Version:  26.1
 OS Platform: Darwin
 RID:         osx-arm64
 Base Path:   /usr/local/share/dotnet/sdk/10.0.100/

.NET workloads installed:
There are no installed workloads to display.
Configured to use workload sets when installing new manifests.
No workload sets are installed. Run "dotnet workload restore" to install a workload set.

Host:
  Version:      10.0.0
  Architecture: arm64
  Commit:       b0f34d51fc

.NET SDKs installed:
  6...

</details>

- Fixes dotnet/aspnetcore#64335

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

Co-authored-by: captainsafia <1857993+captainsafia@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix OpenAPI generation grouping issue with WithGroupName Fix case-insensitive group name matching in OpenAPI document filtering Nov 13, 2025
Copilot AI requested a review from captainsafia November 13, 2025 22:07
Copilot finished work on behalf of captainsafia November 13, 2025 22:07
@captainsafia captainsafia marked this pull request as ready for review November 13, 2025 23:08
@captainsafia captainsafia requested a review from a team as a code owner November 13, 2025 23:08
Copilot AI review requested due to automatic review settings November 13, 2025 23:08
Copilot finished reviewing on behalf of captainsafia November 13, 2025 23:10
Copy link
Contributor

Copilot AI left a comment

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 bug where OpenAPI document filtering incorrectly excluded endpoints when the casing of .WithGroupName() differed from the document name specified in .AddOpenApi(). Since document names are automatically lowercased during registration, but endpoint group name metadata preserves the original casing, the case-sensitive string comparison caused valid endpoints to be excluded from their documents.

Key Changes:

  • Modified the ShouldInclude predicate in OpenApiOptions constructor to use case-insensitive string comparison
  • Added test coverage to verify case-insensitive group name matching

Reviewed Changes

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

File Description
src/OpenApi/src/Services/OpenApiOptions.cs Updated ShouldInclude predicate to use StringComparison.OrdinalIgnoreCase for group name comparison
src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiDocumentService/OpenApiDocumentServiceTests.Paths.cs Added test case verifying case-insensitive matching and added using directive for Microsoft.AspNetCore.OpenApi namespace

@captainsafia captainsafia enabled auto-merge (squash) November 17, 2025 17:28
@captainsafia captainsafia merged commit 4dc0f64 into main Nov 17, 2025
36 of 37 checks passed
@captainsafia captainsafia deleted the copilot/fix-openapi-grouping-issue branch November 17, 2025 18:21
@dotnet-policy-service dotnet-policy-service bot added this to the 11.0-preview1 milestone Nov 17, 2025
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 Generation No Longer Groups Endpoints Using WithGroupName

4 participants