Tuesday, November 26, 2024

Azure APIM Backends with OpenAPI Specifications: Importance of operationId

I recently faced an issue in one of the APIs where as part of importing OpenAPI to Azure APIM, it started throwing an error: "(ValidationError) Operation with the same method and URL template already exists".

Let's have a look at a Minimal Reproducible Example (MRE).

Say I have the following ASP.NET Core API controller that is getting exposed in OpenAPI Spec.
[Route("api/some/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/long-resources")]
[ApiController]
public class ValuesController : ControllerBase
{
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return ["value1""value2"];
    }

    [HttpGet("{id}")]
    public string Get(int id)
    {
        return "value";
    }
}
When I import this to APIM, it's getting imported.

Note the operationId
OpenAPI Specification
Since the code hasn't explicitly specified an operationId, APIM is generating the operationId by following a convention (see Normalization rules for operationId).

Now let's remove the first endpoint and try to import again.
[Route("api/some/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/long-resources")]
[ApiController]
public class ValuesController : ControllerBase
{
    [HttpGet("{id}")]
    public string Get(int id)
    {
        return "value";
    }
}
This time I am getting the error.
(ValidationError) Operation with the same method and URL template already exists
Since we no longer have multiple operations, now for the operationId no de-duplication suffix will be used, but the newly generated operationId is the same operationId that was previously used for"GET: /api/some/very/.../long-resources" endpoint.

We can fix this by adding operationId in the code, as follows.
[Route("api/some/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/long-resources")]
[ApiController]
public class ValuesController : ControllerBase
{
    [HttpGet("{id}", Name = "GetValueById")]
    public string Get(int id)
    {
        return "value";
    }
}
Explicit operationId
So as a practice, we should always consider explicitly specifying operationId in our code rather than letting APIM auto-generate one.And this is going to be very important if you are using APIOps and has custom APIM policy overrides for operations. Because the policies are maintained by operationId and if operationId generation convention is changed for some reason, your APIOps deployments will fail.

Hope this helps.

Happy Coding.

Regards,
Jaliya

No comments:

Post a Comment