Ted
Ted

Reputation: 20184

OpenAPI / Swagger-ui: Auto-generated JSON in form ignores parameter name

EDIT: Found this post after posting here, se answer below

I am using ServiceStack and its OpenApi plugin. I am not sure though if this is an Swagger-ui problem, ServiceStack or something in my code.

I have a POST endpoint where I expect the Customer property to be populated:

[Route("/api/customers/", "POST", Summary = "Creates a new customer")]
public class CreateCustomer : IReturn<CreateCustomerResponse>
{
    [ApiMember(Description = "The customer data", ParameterType = "body", IsRequired = true)]
    public Customer Customer { get; set; }
}

The Customer class has a number of properties, like "Firstname" etc.

When I review this in the swagger-ui, I can see that the "Example value" lacks the name "Customer" that the JSON object "Customer" should be placed within:

enter image description here

If I then press "Try it out"-button, I can see that Swagger-ui sends the "Customer" object directly without specifying that it should be inside the "Customer" (I removed the backslashes and cut out properties from the Customer json for clarity):

curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{  
   "PopulationRegistryNumber": "string",  
   "Firstname": "string",  
   "MiddleName": "string",  
   "Lastname": "string"
 }

What I was expected was:

curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '
{ "Customer": 
   {
       "PopulationRegistryNumber": "string",
       "Firstname": "string",
       "MiddleName": "string",
       "Lastname": "string"
   }
}

Now, if I remove the ServiceStack ApiMember attribute, then the Swagger-ui has the correct JSON, but it adds a separate field in the form for "Customer", that is misleading and should not be there, since it should be part of the body.

enter image description here

Is this "Customer" field a swagger issue, a ServiceStack thing or something I am missing?

Upvotes: 3

Views: 1162

Answers (1)

Ted
Ted

Reputation: 20184

There is a thread on ServiceStack forum, where this exact issue is discussed.

The last post by xplicit comes with a solution, even though its not clear to me how exactly the attributes work together.

The solution, which partly resolves my issue, is:

You can use [ApiMember(ExcludeInSchema=true)] and [ApiMember(ParameterType=“model”)] to exclude properties you don’t want to see in Open API definitions. For example

[Route("/workflow/{ProjectId}", "POST")]
[Api(BodyParameter = GenerateBodyParameter.Always, IsRequired = true)]
public class WorkflowPostRequest : IReturn<Workflow>
{
    [ApiMember(ParameterType = "path", ExcludeInSchema = true)]
    public string ProjectId { get; set; }

    [ApiMember(ParameterType = "model")]
    public Workflow Workflow { get; set; }
} 

will generate this Open API definition:

enter image description here

The forum post is here.

NOTE:

The attribute on the class, [Api(BodyParameter = GenerateBodyParameter.Always, IsRequired = true)], is not needed in my case, the correct JSON and look in swagger works anyways.

So, basically, all you need to do it seems, is to change from ParameterType = "body" to ParameterType = "model"

Also note that variables that are in path, query etc, must manually be excluded using ExcludeInSchema, which is annoying but doable.

Upvotes: 1

Related Questions