How do you sort endpoints in swagger with the minimal api .net 6

I am trying to get the hang of swagger in minimal API. I have the following code:

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(setup => setup.SwaggerDoc("v1", new OpenApiInfo()
{
    Description = "An api that will change your life for ever",
    Title = "Alert Api",
    Version = "v1",
    Contact = new OpenApiContact()
    {
        Name = "Grundfos",
        Url = new Uri("https://grundfos.com")
    }
}));
WebApplication app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

//Map endpoints
app.MapGet("/alerts", async () => Results.Ok());
app.MapGet("/profiles", async () => Results.Ok());

this gives a swagger UI looking like this:

Swagger interface

My question is: How do you sort the endpoints to be under a headline called "alerts" and "profiles"?

Upvotes: 3

Views: 2920

Answers (2)

D G
D G

Reputation: 749

If you have a bunch of related endpoints and you want to group them in one tag SomethingEndpoints, you can do it by creating a static class named SomethingEndpoints and defining an extension method MapSomethingEndpoints() as follows.

Notes:

  • The automatically added tags are only available when passing method Job.
  • Passing (int y) => Job(y) or (int z) => z does not. You need to attach WithTags() manually in this case.
  • I don't know whether it is a feature by design or a bug!

SomethingEndpoints.cs

static class SomethingEndpoints
{
    public static void MapSomethingEndpoints(this IEndpointRouteBuilder routes)
    {
        var group = routes.MapGroup("/api/v1/job");

        group.MapGet("/{x:int}", Job);// no need WithTags!
        group.MapGet("/{y:int}", (int y) => Job(y)).WithTags(nameof(SomethingEndpoints));
        group.MapGet("/{z:int}", (int z) => z).WithTags(nameof(SomethingEndpoints));
    }

    static int Job(int x) => x;
}

Program.cs

var builder = WebApplication.CreateBuilder(args);


builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();


if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.MapSomethingEndpoints();
app.Run();

Upvotes: 1

Vivendi
Vivendi

Reputation: 21057

I think what you are after is something called Tags in swagger.

You can add WithTags at the end of your mapping, like so:

//Map endpoints
app.MapGet("/alerts", async () => Results.Ok()).WithTags("Alerts");
app.MapGet("/profiles", async () => Results.Ok()).WithTags("Profiles");

The result looks like this:

enter image description here


Alternatively you can also take another approach by configuring the AddSwaggerGen method.

In there you can take the first segment of the URL endpoint and use that as the tag name.

For example, the endpoints alerts and alerts/delete will both be placed in a section called alerts.

builder.Services.AddSwaggerGen(c =>
{
    c.TagActionsBy(d =>
    {
        var rootSegment = d.RelativePath?
            .Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
            .FirstOrDefault() ?? "Home";
        return new List<string> { rootSegment! };
    });
})


//Map endpoints without 'WithTags`
app.MapGet("/alerts", async () => Results.Ok());
app.MapGet("/alerts/delete", async () => Results.Ok());
app.MapGet("/profiles", async () => Results.Ok());

enter image description here

Upvotes: 6

Related Questions