Swashbuckle.webapi: Optional parameters in the path generate invalid swagger

Created on 15 Jul 2015  路  8Comments  路  Source: domaindrivendev/Swashbuckle.WebApi

Strange as it may be, if you have a controller method

[Route("{id}")]
public HttpResponseMessage Get(long? id = null)
{
 ...
}

This generates invalid swagger json since the parameter comes out with "required":false

{
    "swagger": "2.0",
    "info": {
        "version": "v1",
        "title": "WebApplication3"
    },
    "host": "localhost:58728",
    "schemes": [
        "http"
    ],
    "paths": {
        "/api/books/{id}": {
            "get": {
                "tags": [
                    "Books"
                ],
                "operationId": "Books_Get",
                "consumes": [],
                "produces": [
                    "application/json",
                    "text/json",
                    "application/xml",
                    "text/xml"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": false,
                        "type": "integer",
                        "format": "int64"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/Object"
                        }
                    }
                },
                "deprecated": false
            }
        }
    },
    "definitions": {
        "Object": {
            "type": "object",
            "properties": {}
        }
    }
}

According to http://swagger.io/v2/schema.json
a "pathParameterSubSchema" is only allowed to have "required":true

I realize that the method is a little strange as its not actually callable without specifying the {id} as part of the URL, however the actual code was a bit more complicated. This was a simplified example to demonstrate the bug.

Most helpful comment

Swagger is a specification (see http://swagger.io/specification/). Swashbuckle generates Swagger. The specification DOES NOT support optional parameters in "path".

All 8 comments

It appears that it would be simply be a matter of changing
https://github.com/domaindrivendev/Swashbuckle/blob/master/Swashbuckle.Core/Swagger/SwaggerGenerator.cs#L181 to

            parameter.required = inPath || !paramDesc.ParameterDescriptor.IsOptional;

Nice catch! Fancy putting together a quick PR?

Closing as its now taken care of by #432

I'm not sure if I get this right, but in WebAPI path-parameters CAN be optional.

In my case, this code:

        [HttpGet("{name}/{functionalKey?}")]
        [HttpPost("{name}/{functionalKey?}")]
        [ProducesResponseType(typeof(TopicEvent), 200)]
        public async Task<IActionResult> Publish([FromRoute]string name, [FromRoute]string functionalKey = null,
            [FromQuery]DateTime? publicationDateUtc = null, [FromQuery]DateTime? expirationDateUtc = null, [FromQuery] int priority = 0, [FromQuery]string payload = null)

... produces this json:

"/publish/{name}/{functionalKey}": {
      "get": {
        "tags": [
          "Publish"
        ],
        "operationId": "PublishByNameByFunctionalKeyGet",
        "consumes": [],
        "produces": [
          "text/plain",
          "application/json",
          "text/json"
        ],
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "functionalKey",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "publicationDateUtc",
            "in": "query",
            "required": false,
            "type": "string",
            "format": "date-time"
          },

The routeattribute already specifies the first two arguments as optional. Why does Swashbuckle still mark them required?

Swagger is a specification (see http://swagger.io/specification/). Swashbuckle generates Swagger. The specification DOES NOT support optional parameters in "path".

Ok, thats a pity. Yet you could also generate multiple routes/endpoints: one for each variant. In my example that would be three of them. Or I could do that myself by specifying all variants in the webapi controller, which I will do for now.

I Have the same issue. I have two route one with route param and one not.
[Route("api/[controller]")] [Route("api/Users/{user_id}/[controller]")] public class AddressesController

It generate for spec for the two but 'user_id' is marked as required for the first one.

@domaindrivendev swagger might not honour is optional, but...

...how about to revert to the behaviour that swashbuckle had in v1.0, where optional parameters were treated as mandatory, thus not generating error.

Solution Nr 1: reverting to v1.0 behavior

the only downside is that inside the description this limitation should be added as a WARNING into description.

this way the developer would not be forced to alter existing code (@ update) neither to not to use optional URI parameters...

Solution Nr 2: let swashbuckle generate the extra routes

really, how about generate all the combinations of optional urls inside swashbuckle?
api/action/method/{a?}/{b?}/{c?}

it can be a bit tricky, i think .NET itself has some limitations, but if we don't specify types, then those 2 routes (1x omitting a, 1x optional b) are the same:
api/action/method/{b}/{c}
api/action/method/{a}/{c}

actually what do matters are types, cause if we do specify types:
api/action/method/{a:int?}/{b:string?}/{c:string?}
then:
api/action/method/{b:string}/{c:string}
api/action/method/{a:int}/{c:string}
are differrent...

anyhow, it's just an algorithm that creates multiple endpoints for SWAGGER. so de facto is the same advice you gave us, but instead of changing the coding behaviour, the tool (swashbuckle) would be transformed to supply integration without coding overhead.

Was this page helpful?
0 / 5 - 0 ratings