In our API we would like to return a object from a external Nuget package when a users makes a call to the endpoint.
This object (Can be viewed here) has a couple of properties. One of them is called Action
. This property has as type IPaymentResponseAction
but can be a set of different action types (You can see them all over here).
The generated swagger does not know about these actions and doesn't generate the required code. Even with the polymorphism setting set.
services.AddSwaggerGen(c =>
{
c.EnableAnnotations();
c.UseOneOfForPolymorphism();
});
Is there a way that i can make these objects show up in my swagger? Maybe with some custom SwaggerGenOptions
?
CodePudding user response:
This can be done using the Swashbuckle.AspNetCore.Annotations
package. Depending on the API design, you can use one of the following approaches.
Response schema doesn't depend on a response code
This approach takes advantage of using oneOf in the response schema. The idea is to make Swashbuckle generate a response schema that would have oneOf
:
responses:
'200':
description: Success
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/CheckoutAwaitAction'
- $ref: '#/components/schemas/CheckoutBankTransferAction'
- $ref: '#/components/schemas/CheckoutDonationAction'
- $ref: '#/components/schemas/CheckoutOneTimePasscodeAction'
# ...
Here is what you need to do:
Add
UseOneOfForPolymorphism
andSelectSubTypesUsing
options to yourAddSwaggerGen
call; make sure yourSelectSubTypesUsing
resolvesIPaymentResponseAction
interface to all the desired implementations your API is returning from a controller method:services.AddSwaggerGen(c => { // ... c.UseOneOfForPolymorphism(); c.SelectSubTypesUsing(baseType => { if (baseType == typeof(IPaymentResponseAction)) { return new[] { typeof(CheckoutAwaitAction), typeof(CheckoutBankTransferAction), typeof(CheckoutDonationAction), typeof(CheckoutOneTimePasscodeAction), // ... }; } return Enumerable.Empty<Type>(); });
Add
SwaggerResponse
annotation to your controller methods. Specify only theIPaymentResponseAction
interface.[HttpGet] [SwaggerResponse((int)HttpStatusCode.OK, "response description", typeof(IPaymentResponseAction))] public IPaymentResponseAction GetPaymentAction() { // ...
This will give you the desired schema in Swagger-UI
:
Please note that Swagger-UI
doesn't support the "Example Value" section if the schema has a oneOf
definition: it will just show a response sample for the first resolved type in the SelectSubTypesUsing
call.
Response schema depends on a response code
It doesn't seem like your case, but I still wanted to mention it as an option.
If the response schema is different for different response codes, you can specify corresponding types directly in the controller:
[HttpPost]
[SwaggerResponse((int)HttpStatusCode.Created, "response description", typeof(CheckoutAwaitAction))]
[SwaggerResponse((int)HttpStatusCode.OK, "response description", typeof(CheckoutBankTransferAction))]
// ...
public IPaymentResponseAction PostPaymentAction()
{
// ...