Ask a Question

c# openapi parameter schema object

SOLVED
more-urgen-jest
Occasional Contributor

c# openapi parameter schema object

is it possible to define a parameter using a ref to a schema? e.g.:

 

 

    "/path/to/here": {
      "get": {
        "responses": {
          "200": {
            "$ref": "#/components/responses/Response"
          }
        },
        "operationId": "get-to-here",
        "description": "Get to here",
        "parameters": [
          {
            "schema": {
              "$ref": "#/components/schemas/Request"
            },
            "in": "query",
            "name": "Request",
            "description": "Request for getting here",
            "required": true
          }
        ],
        "tags": [
          "Here"
        ]
      }
    }

 

 

 

this generates a C# abstract controller as expected via the openapi generator:

 

 

        public abstract Task<IActionResult> GetToHere([FromQuery (Name = "Request")][Required()]Request request);

 

 

 

but the NSwag generator, via a service reference, generates:

 

 

        public async Task<Response> GetToHereAsync(Request request, CancellationToken cancellationToken)
        {
            if (request == null)
                throw new System.ArgumentNullException("request");
    
            var urlBuilder_ = new System.Text.StringBuilder();
            urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/path/to/here?");
            urlBuilder_.Append(System.Uri.EscapeDataString("Request") + "=").Append(System.Uri.EscapeDataString(ConvertToString(request, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
            urlBuilder_.Length--;

 

 

 

rather than adding the primitives in the request object as separate query parameters.

the request is defined as:

 

 

      "Request": {
        "title": "Request",
        "x-stoplight": {
          "id": "blah"
        },
        "type": "object",
        "x-examples": {
          "example": {
            "$ref": "#/components/examples/RequestExample"
          },
          "example Names": {
            "$ref": "#/components/examples/RentalSuburbRangeRequestNames"
          }
        },
        "properties": {
          "Id": {
            "type": "string"
          },
          "Name": {
            "type": "string"
          },
          "OtherName": {
            "type": "string"
          }
        }
      }

 

 

 

any hints much appreciated
7 REPLIES 7
ponelat
Staff

Hi @more-urgen-jest 

 

Yes, you can use schemas in parameters.

You might be looking for Parameter serialization, specifically the `explode` keyword... https://swagger.io/docs/specification/serialization/

 

That will allow each field in an object to be its own query name/value pair.

 

more-urgen-jest
Occasional Contributor

I tried changing it by adding explode: true:

    "/path/to/here": {
      "get": {
        "responses": {
          "200": {
            "$ref": "#/components/responses/Response"
          }
        },
        "operationId": "get-to-here",
        "description": "Get to here",
        "parameters": [
          {
            "schema": {
              "$ref": "#/components/schemas/Request"
            },
            "in": "query",
            "name": "Request",
            "description": "Request for getting here",
            "required": true,
            "explode": true
          }
        ],
        "tags": [
          "Here"
        ]
      }
    }

but when I rebuild the project the output is the same:

        public async Task<Response> GetToHereAsync(Request request, CancellationToken cancellationToken)
        {
            if (request == null)
                throw new System.ArgumentNullException("request");
    
            var urlBuilder_ = new System.Text.StringBuilder();
            urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/path/to/here?");
            urlBuilder_.Append(System.Uri.EscapeDataString("Request") + "=").Append(System.Uri.EscapeDataString(ConvertToString(request, System.Globalization.CultureInfo.InvariantCulture))).Append("&");

updating the packages to the latest versions:

 

    <PackageReference Include="NSwag.ApiDescription.Client" Version="13.17.0">

 


resulted in this output:

 

        public virtual async Task<Response> GetToHereAsync(Request request, CancellationToken cancellationToken)
        {
            if (request == null)
                throw new System.ArgumentNullException("request");

            var urlBuilder_ = new System.Text.StringBuilder();
            urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/path/to/here?");
            foreach (var item_ in Request.AdditionalProperties) { urlBuilder_.Append(System.Uri.EscapeDataString(item_.Key) + "=").Append(System.Uri.EscapeDataString(ConvertToString(item_.Value, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); }
            urlBuilder_.Length--;

 

 

so does that mean that if I want the query parameters to be populated just setting the properties of the object won't do it, I also have to populate AdditionalProperties???

also, it's Request.AdditionalProperties instead of request.AdditionalProperties, which will result in a runtime error?

when I add "style": "form" I get this:

        public virtual async Task<Response> GetToHereAsync(Request request, CancellationToken cancellationToken)
        {
            if (request == null)
                throw new System.ArgumentNullException("request");

            var urlBuilder_ = new System.Text.StringBuilder();
            urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/path/to/here?");
            if (Request.Property1 != null)
            {
                urlBuilder_
					.Append(System.Uri.EscapeDataString("Property1") + "=")
					.Append(System.Uri.EscapeDataString(ConvertToString(Request.Property1, System.Globalization.CultureInfo.InvariantCulture)))
					.Append("&");
            }
            if (Request.Property2 != null)
            {
                urlBuilder_
					.Append(System.Uri.EscapeDataString("Property2") + "=")
					.Append(System.Uri.EscapeDataString(ConvertToString(Request.Property2, System.Globalization.CultureInfo.InvariantCulture)))
					.Append("&");
            }
            foreach (var item_ in Request.AdditionalProperties)
			{
				urlBuilder_
					.Append(System.Uri.EscapeDataString(item_.Key) + "=")
					.Append(System.Uri.EscapeDataString(ConvertToString(item_.Value, System.Globalization.CultureInfo.InvariantCulture)))
					.Append("&");
			}
            urlBuilder_.Length--;

which is what I am trying to get, except for the use of the type again instead of the parameter.

and changing the parameter name property to lower case, "name": "request", fixes that.

        "parameters": [
          {
            "schema": {
              "$ref": "#/components/schemas/Request"
            },
            "in": "query",
            "name": "request",
            "description": "Request for getting here",
            "required": true,
            "explode": true,
            "style": "form"
          }
ponelat
Staff

@more-urgen-jest I don't know NSwag (or C# for that matter). Did you find success? 

more-urgen-jest
Occasional Contributor

yes, your reply pointed me in the right direction, thank you

cancel
Showing results for 
Search instead for 
Did you mean: