Nswag: Web API: Support complex query parameters

Created on 11 May 2016  Â·  15Comments  Â·  Source: RicoSuter/NSwag

public void ActionMethod([FromUri]Point point)
...

should generate the parameters:

  • point.x
  • point.y
committed enhancement

Most helpful comment

Please create a new issue so that we can track this feature...

All 15 comments

This is implemented

@RSuter does NSwag support complex deep objects in the query parameters?

class RequestObject {
public class CommandObjectOne;
public class CommandObjectTwo;
public class CommandObjectThree;
}
Please see "DeepObject" in the spec:
https://swagger.io/docs/specification/serialization/

Is this valid c#?

@RSuter I was just using psudo code as an example. Here's some valid C#

```C#
public class MyRequest
{
public OneCommand OneCommand { get; set; }
public TwoCommand TwoCommand { get; set; }
public ThreeCommand ThreeCommand { get; set; }
}

public class OneCommand
{
    public int SomeNumber { get; set; }
    public int AnotherNumber { get; set; }
}

public class TwoCommand
{
    public string SomeName { get; set; }
    public string SomeDescription { get; set; }
}


public class ThreeCommand
{

    public string SomeName { get; set; }
    public string Value { get; set; }
    public string SomeType { get; set; }
}

```

complex-query-parameters-issue

The question is: What do you expect? Swagger cannot express complex query parameters - they must be primitive or otherwise expanded into multiple parameters....

Swagger's API shows support for DeepObject:

deepObject | true | n/a | n/a | n/a | /users?id[role]=admin&id[firstName]=Alex
-- | -- | -- | -- | -- | --

https://swagger.io/docs/specification/serialization/

Ok, maybe this is a Swagger 3.0 feature? Or how would this look like in an actual swagger spec?

I don't know if it's Swagger 3.0 or not.

{
  "x-generator": "NSwag v11.12.10.0 (NJsonSchema v9.10.10.0 (Newtonsoft.Json v10.0.0.0))",
  "swagger": "2.0",
  "info": {
    "title": "",
    "version": ""
  },
  "host": "localhost:13953",
  "basePath": "",
  "schemes": [
    "http"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/api/My/Route/{Id}": {
      "get": {
        "tags": [
          "Mine"
        ],
        "operationId": "My_Get",
        "parameters": [
          {
            "type": "string",
            "name": "Id",
            "in": "path",
            "required": true,
            "x-nullable": false
          },
          {
            "type": "object",
            "name": "oneCommand",
            "in": "query",
            "x-schema": {
              "$ref": "#/definitions/OneCommand"
            },
            "x-nullable": true
          },
          {
            "type": "object",
            "name": "twoCommand",
            "in": "query",
            "x-schema": {
              "$ref": "#/definitions/TwoCommand"
            },
            "x-nullable": true
          },
          {
            "type": "object",
            "name": "threeCommand",
            "in": "query",
            "x-schema": {
              "$ref": "#/definitions/ThreeCommand"
            },
            "x-nullable": true
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "schema": {
              "$ref": "#/definitions/MyResponseObj"
            },
            "x-nullable": true
          },
          "500": {
            "description": "",
            "schema": {},
            "x-nullable": true
          }
        }
      }
    },
  "definitions": {
    "OneCommand": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "pageNumber",
        "pageSize"
      ],
      "properties": {
        "someNumber": {
          "type": "integer",
          "format": "int32"
        },
        "anotherNumber ": {
          "type": "integer",
          "format": "int32"
        }
      }
    },
    "TwoCommand": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "someName": {
          "type": "string"
        },
        "someDescription ": {
          "type": "string"
        }
      }
    },
    "ThreeCommand": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "someName": {
          "type": "string"
        },
        "value": {
          "type": "string"
        },
        "someType": {
          "type": "string"
        }
      }
    }
  }
}

Hmm, it does look like this is a 3.0 feature. Do you not support 3.0 yet?

OpenAPI 3.0 supports arrays and objects in operation parameters (path, query, header, and cookie) and lets you specify how these parameters should be serialized. The serialization method is defined by the style and explode keywords:

style defines how multiple values are delimited. Possible styles depend on the parameter location – path, query, header or cookie.
explode (true/false) specifies whether arrays and objects should generate separate parameters for each array item or object property.
OpenAPI serialization rules are based on a subset of URI template patterns defined by RFC 6570. Tool implementers can use existing URI template libraries to handle the serialization, as explained below.

I'd imagine that NSwag would detect a complex object and automatically set the "style" to "DeepObject" if the parameter is "[FromQuery]". Although, I'm not sure as I'm very new to these tools.

I just noticed this

NSwag is a Swagger 2.0 API

Sorry to bother you.

The plan is to support v3 eventually, but currently I am doing most of the work and I try to fix other things first...

See https://github.com/RSuter/NSwag/issues/945

Please create a new issue so that we can track this feature...

@RSuter is this coming with the v3 support? Is there an issue tracking it?

Was this page helpful?
0 / 5 - 0 ratings