Invalid openApi Schema when thre is an array of objects in the body

Hi, using service stack 5.0.2

given this dto

[Route("/persons/events/subCategories", “PUT”)]
public class SetEventPersonSubCategories
: IReturn
{
[ApiMember(IsRequired = true, ParameterType = “body”, Name = “subcategories”)]
public List Subcategories { get; set; }
//public SubCategoryWrite Subcategories { get; set; }
}

the generated schema is :

‘/persons/events/subCategories’:
put:
tags:
- persons
operationId: SetEventPersonSubCategoriespersonideventseventidsubCategories_Create
consumes:
- application/json
produces:
- application/json
*parameters:
- name: subcategories
in: body
type: array
items:
$ref: ‘#/definitions/SubCategoryWrite’
collectionFormat: multi
required: true
responses:
‘200’:
description: Success
schema:
$ref: ‘#/definitions/SetEventPersonSubCategoriesResponse’
deprecated: false
parameters:
- $ref: ‘#/parameters/Accept’

gives the following schema errors in https://editor.swagger.io/

Schema error at paths[’/persons/{personid}/events/{eventid}/subCategories’].put.parameters[0]
should NOT have additional properties
additionalProperty: type, items, collectionFormat, name, in, required
Jump to line 967
Schema error at paths[’/persons/{personid}/events/{eventid}/subCategories’].put.parameters[0].in
should be equal to one of the allowed values
allowedValues: header, formData, query, path
Jump to line 968
Schema error at paths[’/persons/{personid}/events/{eventid}/subCategories’].put.parameters[0].items
should NOT have additional properties
additionalProperty: $ref
Jump to line 970
Schema error at paths[’/persons/{personid}/events/{eventid}/subCategories’].put.parameters[0].collectionFormat
should be equal to one of the allowed values
allowedValues: csv, ssv, tsv, pipes
Jump to line 972

As you can see , there is something wrong with the array declaration ,

if I replace
public List Subcategories { get; set; }
with
public SubCategoryWrite Subcategories { get; set; }

it does not complain anymore

Can you please help ?

Don’t use body, the entire Response DTO is the body of the Response not just the Subcategories property.

Hi, I am facing the same problem. What other than “body” should be uses as parameter type?

[Route("/portal/{Participant}/stock/", "PUT", Summary = "Updates the product stock of a given portal participant.")]
[ApiResponse(HttpStatusCode.OK, "Stocks successfully updated")]
public class UpdatePortalStockRequest : IReturnVoid
{
    [ApiMember(Description = "...", IsRequired = true, ParameterType = "path")]
    public string Participant { get; set; }

    [ApiMember(Description = "...", IsRequired = true, ParameterType = "???")]
    public IList<PortalStock> PortalStocks { get; set; }
}

Don’t put anything, leave the default, the entire Request DTO is the body.

This still results in an error in the swagger editor

put:
  tags:
    - portal
  summary: Updates the product stock of a given portal participant.
  description: Updates the product stock of a given portal participant.
  operationId: UpdatePortalStock
  consumes:
    - application/x-www-form-urlencoded
  produces:
    - application/json
  parameters:
    - name: Participant
      in: path
      description: ...
      type: string
      required: true
    - name: PortalStocks
      in: formData
      description: ...
      type: array
      items:
        $ref: '#/definitions/PortalStock'
      collectionFormat: multi
      required: true
    - name: body
      in: body
      schema:
        $ref: '#/definitions/UpdatePortalStockRequest'
  responses:
    '200':
      description: Stocks successfully updated
    '204':
      description: No Content

Errors

Hide

Semantic error at paths./portal/{Participant}/stock/.put.parameters

Parameters cannot have both a “in: body” and “in: formData”, as “formData” will be the body

Jump to line 81

Structural error at paths./portal/{Participant}/stock/.put.parameters.1.items

should NOT have additional properties additionalProperty: $ref

Jump to line 90

What’s that YAML generated from?

You can use query in POST/PUT Request DTOs to have it not have it defined as a conflicting formData.

Or you can disable the body from being generated per Request DTO by annotating it with:

[Api(BodyParameter = GenerateBodyParameter.Never)]
public class UpdatePortalStockRequest : IReturnVoid { ... }

Or prevent any body parameters from being defined by default with:

Plugins.Add(new OpenApiFeature {
    DisableAutoDtoInBodyParam = true
});

FYI I’d recommend against using interfaces in DTOs, esp. for IList<T> which is almost always a container for the concrete List<T> which your DTO Service Contracts should be using instead.