I was trying to use AutoRest to generate a client SDK for one of my API’s. This turned out not to be the success I was hoping for.
Yesterday I explained that I got into trouble because an OperationId was missing. But after adding it, it still didn’t work. Instead I got the following error message:
Duplicate operation detected
Here was the API controller I was using:
[Route("generate")] | |
public class GenerationController : ControllerBase | |
{ | |
[HttpPost("upload/file/{targetFileName}.{extension}")] | |
public IActionResult Upload(IFormFile templateFile, IFormFile xmlFile, string targetFileName, string extension) | |
{ | |
} | |
[HttpPost("upload/uri/{targetFileName}.{extension}")] | |
public async Task<IActionResult> Upload([FromQuery] Uri template, IFormFile xmlFile, string targetFileName, string extension) | |
{ | |
} | |
} |
AutoRest uses the OpenAPI generated through Swashbuckle. When I took a look at the OpenAPI file, I noticed that indeed the same OperationId was used:
"/generate/upload/file/{targetFileName}.{extension}": { | |
"post": { | |
"tags": [ | |
"Generation" | |
], | |
"operationId": "upload" | |
}, | |
"/generate/upload/uri/{targetFileName}.{extension}": { | |
"post": { | |
"tags": [ | |
"Generation" | |
], | |
"operationId": "upload" | |
} | |
}, |
This is because I was using the ActionName as the OperationId. As I have multiple Action methods with the same name they all result in the same OperationIe
To fix it, you can do 2 things:
- Using the [SwaggerOperation] attribute
- Using the Name property on the Http attribute ([HttpGet], [HttpPost],…)
Using the [SwaggerOperation] attribute
By adding a [SwaggerOperation] attribute to the controller action method, you can control the generated OperationId:
[HttpPost("upload/file/{targetFileName}.{extension}")] | |
[SwaggerOperation("GenerateFromUploadedFile")] | |
public IActionResult Upload(IFormFile templateFile, IFormFile xmlFile, string targetFileName, string extension) | |
{ | |
} |
Using the Name property
An alternative solution is to use the Name property on the HTTP routing attributes:
[HttpPost("upload/file/{targetFileName}.{extension}", Name="GenerateFromUploadedFile")] | |
public IActionResult Upload(IFormFile templateFile, IFormFile xmlFile, string targetFileName, string extension) | |
{ | |
} |