dotnet / dotnet/aspnetcore

Using MapGroup() with MapControllers() results in incorrect path in Swagger

Open
#57,598 2 comments 2 reactions 0 assignees View on GitHub
area-mvc
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 10h
Merged PRs (30d)
281

Description

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Describe the bug

When doing this:
```csharp
app.MapGroup("prefix").MapControllers();
```

Assuming there is a `FooController`, the generated OpenAPI spec incorrectly says the path is `/Foo` instead of `/prefix/Foo`:

```
...
paths": {
"/Foo": {
"get": {
"tags": [
"Foo"
],
"responses": {
"200": {
"description": "Success",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
},
"application/json": {
"schema": {
"type": "string"
}
},
"text/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
...
```

Trying to curl both `/Foo` and `/prefix/Foo` shows that the wrong path was generated in the OpenAPI spec:
```
$ curl -f http://localhost:5147/Foo
curl: (22) The requested URL returned error: 404
$ curl -f http://localhost:5147/prefix/Foo
It works!
```

Interestingly, this problem only happens with `MapControllers()` and minimal API endpoints created using `MapGet()` for example don't experience this problem. See the steps to reproduce to see what I mean.

### Expected Behavior

The OpenAPI spec should generate the correct path when using `MapGroup()` with `MapControllers()`.

### Steps To Reproduce

#### Program.cs
```csharp
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApiExplorer;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddControllers();

var app = builder.Build();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGroup("prefix").MapGet("/Bar", () => "It works!\n");
});
app.MapGroup("prefix").MapControllers();

app.UseSwagger();
app.UseSwaggerUI();

// Print relative paths
var p = app.Services.GetService()!;
foreach (var group in p.ApiDescriptionGroups.Items)
{
foreach (var api in group.Items)
{
Console.WriteLine(api.RelativePath);
}
}

app.Run();

[ApiController]
[Route("[controller]")]
public class FooController : Controller
{
[HttpGet]
public string Get() => "It works!\n";
}
```

```
$ dotnet run
Building...
prefix/Bar
Foo
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5147
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: /home/brian/projects/SwaggerBugExample/SwaggerBugExample
```

```
$ curl -f http://localhost:5147/swagger/v1/swagger.json
{
"openapi": "3.0.1",
"info": {
"title": "SwaggerBugExample",
"version": "1.0"
},
"paths": {
"/Foo": {
"get": {
"tags": [
"Foo"
],
"responses": {
"200": {
"description": "Success",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
},
"application/json": {
"schema": {
"type": "string"
}
},
"text/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/prefix/Bar": {
"get": {
"tags": [
"SwaggerBugExample"
],
"responses": {
"200": {
"description": "Success",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
}
}
}
}
}
},
"components": { }
```

```
$ curl -f http://localhost:5147/Foo
curl: (22) The requested URL returned error: 404
$ curl -f http://localhost:5147/prefix/Foo
It works!
$ curl -f http://localhost:5147/prefix/Bar
It works!
```

### Exceptions (if any)

_No response_

### .NET Version

8.0.401

### Anything else?

![image](https://github.com/user-attachments/assets/373024f6-4cd9-4781-ae23-be54eafff6f1)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.