Skip to main content
Version: 0.3.x

Endpoint Grouping & OpenAPI Tags

Sharkable provides automatic endpoint grouping, OpenAPI tags, and OperationId generation for ISharkEndpoint endpoints.

How grouping works

By default, each ISharkEndpoint class becomes its own route group. The group name is derived from the class name by stripping the Endpoint/Service/Controller suffix.

public class UserEndpoint : ISharkEndpoint
{
public void AddRoutes(IEndpointRouteBuilder app)
{
app.MapGet("profile", () => "user profile");
}
}

URL: api/user/profile — group name user, tag user.

Explicit grouping with [EndpointGroup]

Multiple endpoint classes can share the same URL prefix and OpenAPI tag.

[EndpointGroup("admin")]
public class UserEndpoint : ISharkEndpoint
{
public void AddRoutes(IEndpointRouteBuilder app)
{
app.MapGet("users", () => Results.Ok(users));
}
}

[EndpointGroup("admin")]
public class RoleEndpoint : ISharkEndpoint
{
public void AddRoutes(IEndpointRouteBuilder app)
{
app.MapGet("roles", () => Results.Ok(roles));
}
}

Both under api/admin/..., sharing filters and middleware.

OpenAPI tags via [SharkTag]

Override the default tag (derived from group name) with explicit tags.

[SharkTag("admin")]
[SharkTag("management")]
public class UserEndpoint : ISharkEndpoint
{
public void AddRoutes(IEndpointRouteBuilder app)
{
app.MapGet("users", () => Results.Ok(users));
}
}

OpenAPI tag: ["admin", "management"]. Repeatable attribute for multiple tags.

Auto OperationId

OperationId is automatically generated for every route: {groupName}_{httpMethod}_{relativePath}.

// Route: GET /api/test/hello
// OperationId: test_GET_hello

// Route: POST /api/admin/users
// OperationId: admin_POST_users

Manual .WithOperationId() or .WithMetadata(new EndpointNameMetadata(...)) in your AddRoutes() method takes precedence over auto-generation.

Configuration

Endpoint format (case style) is configurable via SharkOption:

builder.Services.AddShark(opt =>
{
opt.Format = EndpointFormat.SnakeCase; // default: CamelCase
opt.ApiPrefix = "api"; // default
});
FormatGroup TestUserURL
CamelCase (default)testUserapi/testUser/...
SnakeCasetest_userapi/test_user/...
ToLowertestuserapi/testuser/...
UnChangedTestUserapi/TestUser/...

Old-style [SharkEndpoint] endpoints (AOT-incompatible)

⚠️ Attribute-based endpoints use runtime reflection and do not work in Native AOT publishing. Use ISharkEndpoint for AOT-safe code.

Attribute-based endpoints also get OpenAPI tags and OperationId support:

[SharkEndpoint]
[SharkTag("catalog")]
public class CatalogEndpoint
{
[SharkMethod("items/{id}", SharkHttpMethod.GET)]
public Item? GetItem(int id) { ... }
}