Generate readable APIs clients by setting unique and meaningful operationId in Swagger Documentation

Giuseppe Mariano
2 min readMay 3, 2021

--

I’ve recently figured out that properly setting operationId in swagger documentation can avoid a lot of problems while using code generators for api clients. Moreover, setting meaningful values leads to readable code.

operationId is an “optional” unique string used to identify an operation. If provided, these IDs must be unique among all operations described in your API.
Due to its use in code generators, it should also have a meaningful value.

/users:
get:
operationId: getUsers
summary: Gets all users
...
post:
operationId: addUser
summary: Adds a new user
...
/user/{id}:
get:
operationId: getUserById
summary: Gets a user by user ID
...

Some common use cases for operationId are:

  • Some code generators use this value to name the corresponding methods in code.
  • Links can refer to the linked operations by operationId.

Problems:

Problem 1

For some code generators, like AutoRest, operationId is required and if not specified you get errors like this:

FATAL: OperationId is required for all operations. 

Problem 2

Because some code generators use operationId to name the corresponding methods, as well as being unique, operationId must also have a meaningful name.
Most of the time people solve this problem by setting it like this:

services.AddSwaggerGen(options =>
{
options.CustomOperationIds(apiDesc => $"{apiDesc.ActionDescriptor.RouteValues["controller"]}_{apiDesc.ActionDescriptor.RouteValues["action"]}");
...

Unfortunately this is not good enough because, in case of method overloads in the same controller, you get errors like this:

[FATAL] Error generating client model: Found operation objects with duplicate operationId ‘xxx’. OperationId must be unique among all operations described in the API

Solution:

You can use Swashbuckle Operation Filter to generate operation ids based on controller and action names, adding a numeric suffix to the operationId if one with the same id already exists. Enjoy the result:

services.AddSwaggerGen(options =>
{
options.OperationFilter<SwaggerOperationIdFilter>();
...

--

--