1
votes

I have a backend API (that implements ApiController) which I'd like to put behind an APIM API. ApiController allows us to discriminate between two different GET operations based on the query parameters that are passed in. When I attempt to define these endpoints in APIM, I get the following error:

enter image description here

The message suggests an endpoint is defined solely by the path and operation. But that seems to contradict documentation I found here which suggests there's a way to differentiate between operations based on query parameters:

Required parameters across both path and query must have unique names. (In OpenAPI a parameter name only needs to be unique within a location, for example path, query, header. However, in API Management we allow operations to be discriminated by both path and query parameters (which OpenAPI doesn't support). That's why we require parameter names to be unique within the entire URL template.)

I have an ApiController that defines two different Get operations, differing only by the query parameters. How do I represent that in my APIM API?

2
Are you sure your query parameters are marked as required generated OpenAPI spec?Vitaliy Kurokhtin
Yup. Just checked the OpenAPI Specification in JSON. The fields I checked as "required" in the web portal have a "required": true property setting.BobbyA
Do you mind sharing open api spec?Vitaliy Kurokhtin

2 Answers

1
votes

The problem comes from multiple operation objects with the same OperationId. This is invalid swagger. In the Swagger file did not match the name of the selected API, so change the title attribute of the doc tag to match the destination API it worked..

Here is a similar SO thread you could refer to.

1
votes

I got my answer from Azure support, sharing the info here:

APIM endpoints are defined by the path, method, and the name you assign to the operation. To differentiate between two GET endpoints to the same controller, differing only by query parameters, you need to hardcode required query parameters into the path. See the following two images:

Get Endpoint 1

Get Endpoint 2

In the latter image, the hardcoded query parameter is classified by the UI as a template parameter, but it still behaves like a regular query parameter. Query arguments defined in this way:

  • Are required
  • Can appear in anywhere in a request's list of query arguments
  • Are not case-sensitive
  • Are listed as a "Request Parameter" along side all other path parameters and query arguments in the Development Portal

Edit:

There's a typo in the screenshots. The URLs are case sensitive, and the casing of "blah" were different in each case. Here's what the the Open API Specification looks like when the casing is consistent. The overloaded path (with the query parameter hardcoded into the path template) appears in a section called x-ms-paths:

{
    "swagger": "2.0",
    "info": {
        "title": "Echo API",
        "version": "1.0"
    },
    "host": "<hostUrl>",
    "basePath": "/echo",
    "schemes": ["https"],
    "securityDefinitions": {
        "apiKeyHeader": {
            "type": "apiKey",
            "name": "Ocp-Apim-Subscription-Key",
            "in": "header"
        },
        "apiKeyQuery": {
            "type": "apiKey",
            "name": "subscription-key",
            "in": "query"
        }
    },
    "security": [{
        "apiKeyHeader": []
    }, {
        "apiKeyQuery": []
    }],
    "paths": {
        "/Blah": {
            "get": {
                "operationId": "blah",
                "summary": "Blah",
                "responses": {}
            }
        }
    },
    "tags": [],
    "x-ms-paths": {
        "/Blah?alpha={alpha}": {
            "get": {
                "operationId": "blah2",
                "summary": "Blah2",
                "parameters": [{
                    "name": "alpha",
                    "in": "query",
                    "required": true,
                    "type": "string"
                }],
                "responses": {}
            }
        }
    }
}