Sorry, these posts are getting so long…
OK, I understand Swagger is a descriptor of the API, not a definer, and I’m completely open to this.
How do I define a Swagger published API endpoint, advertising a DTO based parameter of type workflow?
Bear in mind that I might also have to allow path variables (for example a ProjectId
), although according to the OpenAPI stuff, they would have to not be in the body if another parameter is already defined as ‘in body’.
My intended API use is to say SaveWorkflow_POST(Workflow data,Guid projectid)
In non-Swagger-API-terms my assumption is that I would define my Request object as
[Route("/{ProjectId}/workflow", "POST")]
public class WorkflowPostRequest: Workflow, IReturn<Workflow>
{
public Guid ProjectId { get; set; }
}
This does exactly what I require, is the way I’ve always used SS APIs, and I can simply send a POST to /projidguid/workflow
with a body containing a json object such as
{
"name":"workflow1",
"description","Awesome workflow, Jason!"
"definition": { "x":"1","y":"2" }
"actions": [ "blah", "blah" ]
}
Now, I want to describe this in Swagger. How do I do this? Can you show me an example of the attributes required to automatically generate it?
I don’t want a signature of
SaveWorkflow_POST(string name, string description, DefObject definition, string[] actions, Guid projectid)
I simply want
SaveWorkflow_POST(Workflow data,Guid projectid)
Here are some of the experiments we tried to solve it ourselves:
Inheriting from Workflow
simply provides a dummy object so that ServiceStack has somewhere to dump the body object data into, rendering the internal workflow
property redundant, but critical for the Swagger API generation:
[Route("/{ProjectId}/workflow", "POST")]
public class WorkflowPostRequest: Workflow, IReturn<Workflow>
{
[ApiMember(ParameterType = "path")]
public Guid ProjectId { get; set; }
[ApiMember(ParameterType = "body")]
public Workflow workflow { get; set; } <*** This is redundant, but essential for the Swagger signature
}
The extra ‘dummy’ workflow is the only way to have the system export a valid parameter with type Workflow.
We want
[Route("/{ProjectId}/workflow", "POST")]
public class WorkflowPostRequest: IReturn<Workflow>
{
[ApiMember(ParameterType = "path")]
public Guid ProjectId { get; set; }
[ApiMember(ParameterType = "body")]
public Workflow workflow { get; set; }
}
Adding [ApiMember(ParameterType = “body”)] to any member tells the OperationFilter not to output the properties of the base class, but to only export OpenAPI attributed parameters. The “body” one is effectively ‘promoted’ to be the only item populatable from the body of the request, thus implying that the request body itself is a serialised instance of a Workflow
.
How else can I do this?
Please actually try this in swagger-ui.
Here is exactly what a definition described above should look like:
Note that the sample data is not (and should not be)
"workflow" {
{
"Definition": "string",
"Description": "string",
"ProjectId": "string",
"ScriptId": "string",
"WorkflowId": "string"
}
}
It should not have "workflow":
because that is not defined in the argument list of the Swagger JSON, which is also why your '“Example Value” on the right does not contain it, but doesn’t work.
So my question is; is your sample value incorrectly generated, or is your Swagger definition of the Model itself wrong?
Let me somehow move the [ApiMember(ParameterType = "body")]
onto the WorkflowRequest
object, and tell Swagger to advertise it as a body parameter of type Workflow
and I believe this would all be correct
It looks to be a real problem, impacting people using swagger JSON based tools such as NSwagStudio to create client APIs with POST/PUT/PATCH data in a body.
I suspect that whatever you decide to resolve the SS swagger-ui bug Example Code bug, you’ll also have resolved this issue.