HDOT-1743 Allow to expose polymorphic types in Swagger API #2063
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem
Currently, there is no way to expose derived types in Swagger API description. For example, consider the following code:
In this example, only the
BaseObject
will be exposed in Swagger.DerivedObject
andAnotherDerivedObject
will be missing from JSON with API definition, and the only way to expose them is to add some other API method that will explicitly accept or return any of these derived types.On the other hand, we don't want to enable polymorphism globally, as this might break existing API (e.g. any action from
vc-module-customer
that works with aMember
class).Solution
Since the creation of VC platform v3, polymorphism support in Swashbuckle improved significantly. Now we actually can use it in actions, and the resulting document will be suitable for AutoRest (e.g. to generate API clients for storefront). An example mentioned above can be reworked like this to expose derived models:
This will expose
BaseObject
,DerivedObject
andAnotherDerivedObject
in Swagger API description (despite the fact thatGetObjects()
method still has only the base type in its signature), and it won't break other API. However, to use this approach, Swashbuckle configuration code needs to be changed a bit.Proposed of changes
So, I did the following things to achieve this:
Swashbuckle.AspNetCore.Annotations
package;EnableAnnotations()
method have the following meaning:enableAnnotationsForPolymorphism
allows to use theSwaggerSubType
attribute to specify expected derived classes;enableAnnotationsForInheritance
retains models inheritance hierarchy. For example, if we generate a Swagger API documentation for the example mentioned above with this parameter set tofalse
, it will not contain theBaseObject
type - instead,DerivedObject
andAnotherDerivedObject
will include its properties. With this parameter set totrue
, the hierarchy will be preserved.Additional context (optional)
This approach works and does not break any existing clients generated by AutoRest. However, it has some limitations:
BaseObject
has any abstract or virtual properties that are overridden in derived types, Swashbuckle will include these properties both toBaseObject
and to derived types. However,AutoRest
does not understand that and produces an error likeFATAL: System.InvalidOperationException: Found incompatible property types , for property 'someVirtualProperty' in schema inheritance chain
. A solution for this would be to avoid using abstract and virtual properties for such types.AbstractTypeFactory
instead of custom attributes to find descendant types. However, this might require extending theTypeInfo
, so that we could explicitly specify what types can be exposed in Swagger API.Make sure these boxes are checked: