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
UseOneOfForPolymorphismandSelectSubTypesUsingoptions to yourAddSwaggerGencall; make sure yourSelectSubTypesUsingresolvesIPaymentResponseActioninterface 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
SwaggerResponseannotation to your controller methods. Specify only theIPaymentResponseActioninterface.[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()
{
// ...
