I’m using 5.1.0 to generate our API. A customer has tried to import the resulting openapi.json file into Swagger Editor and has come up with a bunch of validation errors. I’ve seen similar topics in the forum but they all seem to suggest the issue was fixed in 4.9.x.
My DTO is:
[DataContract]
[Route(“/candidate”, “PUT”, Summary = “Create or update a candidate”)]
public class CandidatePut : IReturn, IProfilePutRequest
{
// Unique to this put
[DataMember]
[ApiMember(Description = “Details of the candidate to update or add”, IsRequired = true)]
[ServiceField(Required = true)]
public Candidate candidate { get; set; }
}
and the Swagger Editor shows:
put:
tags:
- candidate
summary: Create or update a candidate
description: Create or update a candidate
operationId: CandidatePut_Create
consumes:
- application/x-www-form-urlencoded
produces:
- application/json
parameters:
- name: candidate
in: formData
schema:
$ref: ‘#/definitions/Candidate’
description: Details of the candidate to update or add
required: true
- name: body
in: body
schema:
$ref: ‘#/definitions/CandidatePut’
responses:
‘200’:
description: Success
schema:
$ref: ‘#/definitions/CandidatePutResponse’
deprecated: false
parameters:
- $ref: ‘#/parameters/Accept’
and errors of:
Semantic error at paths./candidate.put.parameters
Parameters cannot have both a “in: body” and “in: formData”, as “formData” will be the body
Jump to line 114
Schema error at paths[‘/candidate’].put.parameters[0]
should NOT have additional properties
additionalProperty: schema, name, in, description, required
Jump to line 114
Schema error at paths[‘/candidate’].put.parameters[0].in
should be equal to one of the allowed values
allowedValues: body, header, query, path
Jump to line 115
Any ideas or hints on what I am missing to generate a valid schema.
Are you using the newer OpenApiFeature? if not you should switch to that instead, if you are please include the full steps to view the validation errors including all missing DTOs like Candidate that is required to repro the issue.
I am using the latest OpenAPI feature. I’ve been able to produce a simple sample using the latest nugget packages that shows the error. Basically compile and run, then open the openapi.json in Swagger Editor to see the schema errors.
Unfortunately I can’t figure out or find any help on how to upload the sample.
Ah OK, I thought you might have some special process to upload projects. Unfortunately I can’t access GitHub so the project is here on onedrive - hopefully you can access it. The tool my client has been trying to use and therefore the tool I am trying to test with is (Swagger Editor - you can load a file or from a URL via the “File” option at the top of the screen.
Once the file or URL has been processed you should be able to see all the validation errors in the right hand panel:
The issue is ServiceStack supports multiple ways of calling your Service whereas the Swagger Editor is stricter than the Swagger UI and only wants one way to be specified.
You can disable generating the body input option with:
Then it will only generate the formData input option, the problem then becomes Swagger Editor doesn’t allow submitting Complex Types via formData even though ServiceStack supports it so you couldn’t have a complex type property like Candidate:
public class CandidatePut : IReturn<CandidatePutResponse>
{
public Candidate candidate { get; set; }
}
You would instead need to keep Request DTOs flat so they only contain (non complex) scalar types, in this case moving all properties of Candidate to your Request DTO, e.g:
public class CandidatePut : IReturn<CandidatePutResponse>
{
public Int32 CandidateRef { get; set; }
}
This does make your Services more interoperable as most external clients don’t support it and there’s not an official standard for populating Complex Type via queryString or formData.
If you go this route then you could easily populate the Candidate DTO from the Request DTO using the built-in Auto Mapping Utils, e.g:
public class CandidateService : Service
{
public object Any(CandidatePut request)
{
var candidate = request.ConvertTo<Candidate>();
}
}
If you don’t need the FormData support documented in the OpenApi doc then you can decorate the service params with [ApiMember(ParameterType = "model")] so it will be body only eg:
public class CandidatePut : IReturn<CandidatePutResponse>
{
[ApiMember(ParameterType = "model")]
public Candidate candidate { get; set; }
}