Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add polymorphism support to generated OpenAPI json and UI #1397

Closed
asvishnyakov opened this issue Aug 1, 2018 · 8 comments
Closed

Add polymorphism support to generated OpenAPI json and UI #1397

asvishnyakov opened this issue Aug 1, 2018 · 8 comments
Assignees
Labels

Comments

@asvishnyakov
Copy link
Contributor

asvishnyakov commented Aug 1, 2018

@asvishnyakov commented on Tue Mar 20 2018

Research point: https://github.com/Azure/autorest/blob/master/docs/developer/guide/defining-clients-swagger.md#polymorphism


@asvishnyakov commented on Thu Aug 02 2018

Updated 27 Mar 2019

Status:

Resolution: the blocking issue is UI support: swagger ui has no support of polymorphism, while ReDoc has no built-in console. For OpenAPI generation we may have a few solutions, code generation already ready for polymorphism and not require any additional actions.

@asvishnyakov asvishnyakov changed the title Add polymorphism support to storefront Add polymorphism support to generated OpenAPI Aug 1, 2018
@asvishnyakov asvishnyakov changed the title Add polymorphism support to generated OpenAPI Add polymorphism support to generated OpenAPI and UI Aug 1, 2018
@asvishnyakov asvishnyakov changed the title Add polymorphism support to generated OpenAPI and UI Add polymorphism support to generated OpenAPI json and UI Aug 1, 2018
@Woland2k
Copy link
Contributor

Woland2k commented Aug 1, 2018

don't swagger UI is that critical, unless it crashes

@yecli yecli added this to the Operations milestone Apr 24, 2019
yecli added a commit that referenced this issue Apr 25, 2019
… Swashbuckle:

- Working prototype for polymorphic object passing through API.
- Added filters for adding discriminator to the schema;
- Each polymorphic type should have property "Type" containig its real type;
- Filters added to module sawgger docs and general one;
TODO:
- Need to add Registrar for registering polymorphic types and use it inside Swagger config;
- Possible to add interface ISupportPolymorphicAPI with string Type => GetType() property.
yecli added a commit that referenced this issue Apr 25, 2019
…ng Swashbuckle:

- Working prototype for polymorphic object passing through API.
- Added filters for adding discriminator to the schema;
- Each polymorphic type should have property "Type" containig its real type;
- Filters added to module sawgger docs and general one;
TODO:
- Need to add Registrar for registering polymorphic types and use it inside Swagger config;
- Possible to add interface ISupportPolymorphicAPI with string Type property which is used as discriminator in OpenAPI doc.
@yecli
Copy link
Contributor

yecli commented Apr 25, 2019

It is working. Storefront is receiving derived objects together with base ones in array using autorest client.
Sample prototype extending Platform API implemented in this commit.

yecli added a commit that referenced this issue Apr 29, 2019
…ng Swashbuckle:

- Added PolymorphicBaseClassAttribute by which base classes should be marked for OpenAPI polymorphism;
- Supported OpenAPI docs generation using this attribute for independent module and common docs;
@yecli yecli self-assigned this Apr 30, 2019
yecli added a commit that referenced this issue Apr 30, 2019
- Moved polymorhic classes declaration to module manifest, e.g.:
    <openAPIPolymorphicTypes>        <assemblyQualifiedTypeName>VirtoCommerce.Domain.Cart.Model.LineItem, VirtoCommerce.Domain</assemblyQualifiedTypeName>
    </openAPIPolymorphicTypes>
Need to use assembly qualified names here;
- Removed attribute that marks class polymorphic for swagger;
- All polymorhic classes should have "Type" property to store type information - Type.Name (or Type.FullName, if UseFullTypeNameInSwagger is set to true for module);
@yecli
Copy link
Contributor

yecli commented Apr 30, 2019

Usage example:
Add info about base polymorphic types to your module manifest (assembly qualified name), so not info on derived types needed:

    <openAPIPolymorphicTypes>
        <assemblyQualifiedTypeName>VirtoCommerce.Domain.Cart.Model.LineItem, VirtoCommerce.Domain</assemblyQualifiedTypeName>
    </openAPIPolymorphicTypes>

Your base and derived types should have property public string Type containing value Type.Name (or Type.FullName in case UseFullTypeNameInSwagger = true for the module).

@asvishnyakov
Copy link
Contributor Author

@yecli Can we do that in code? I don't think it's good idea to put .NET-specific information into manifest. Also, in code we can use nameof() operator and use Assembly class, while here we can make mistake in type & assembla names

@yecli
Copy link
Contributor

yecli commented May 6, 2019

@asvishnyakov First it was implemented in code using custom attribute for polymorphic base type. But there were some problems when we want to make type from dependent assembly as polymorphic base for specific module (e.g. LineItem from Domain for Cart module) - in such cases we would need to load dependent assemblies to search polymorphic types. Moved polymorphic types declaration to module manifests for explicit and clear declaration. Also we already use assembly qualified type names in manifest - for defining module type.

Agree with you, better to do this in the code. @tatarincev said the same and advised to use AbstractTypeFactory for registering polymorphic types. Going to try this solution.

yecli added a commit that referenced this issue May 7, 2019
- Added IPolymorphismRegistrar to register polymorphic types and their discriminator fields for the modules. AbstractTypeFactory is used for getting registered descendant types;
@yecli
Copy link
Contributor

yecli commented May 7, 2019

Added special interface to register type to be polymorphic for the module:

    public interface IPolymorphismRegistrar
    {
        IPolymorphicBaseTypeInfo[] GetPolymorphicBaseTypes(string moduleName);
        void RegisterPolymorphicBaseType(string moduleName, IPolymorphicBaseTypeInfo polymorphismBaseTypeInfo);
    }

Example of usage for Customer module polymorphism (Member class and its descendants):

            // Register Member descendants in AbstractTypeFactory
            AbstractTypeFactory<Member>.RegisterType<Organization>().MapToType<OrganizationDataEntity>();
            AbstractTypeFactory<Member>.RegisterType<Contact>().MapToType<ContactDataEntity>();
            AbstractTypeFactory<Member>.RegisterType<Vendor>().MapToType<VendorDataEntity>();
            AbstractTypeFactory<Member>.RegisterType<Employee>().MapToType<EmployeeDataEntity>();

…
            // Use IPolymorphismRegistrar to tell OpenAPI doc generator to use polymorphism for Member and its descendants
            var polymorphismRegistrar = _container.Resolve<IPolymorphismRegistrar>();
            polymorphismRegistrar.RegisterPolymorphicBaseType(ModuleInfo.Id, new PolymorphicBaseTypeInfo<Member>(nameof(Member.MemberType)));

yecli added a commit that referenced this issue May 7, 2019
… Swashbuckle:

- Removed redundant changes;
yecli added a commit that referenced this issue May 8, 2019
- Reworked Polymorphism registration to use only AbstractTypeFactory and one Document filter;
- Added Discriminator field to TypeInfo<BaseType> which should be filled after RegisterType() for proper polymorphism work;
@yecli
Copy link
Contributor

yecli commented May 8, 2019

Next mechanism rework: left only AbstractTypeFactory as a source for OpenAPI polymorphism registration.

Usage - when registering type in AbstractTypeFactory, need to fill TypeInfo.Discriminator property with the name of base class discriminator property.
Example for Member type in vc-module-customer:

            // Register Member descendants in AbstractTypeFactory
            AbstractTypeFactory<Member>.RegisterType<Organization>().MapToType<OrganizationDataEntity>().Discriminator = nameof(Member.MemberType);
            AbstractTypeFactory<Member>.RegisterType<Contact>().MapToType<ContactDataEntity>().Discriminator = nameof(Member.MemberType);
            AbstractTypeFactory<Member>.RegisterType<Vendor>().MapToType<VendorDataEntity>().Discriminator = nameof(Member.MemberType);
            AbstractTypeFactory<Member>.RegisterType<Employee>().MapToType<EmployeeDataEntity>().Discriminator = nameof(Member.MemberType); 

Generated OpenAPI doc:
PolymorphicOpenAPI_VirtoCommerce.Customer.zip

@yecli
Copy link
Contributor

yecli commented Sep 18, 2019

Closing as not applicable.

@yecli yecli closed this as completed Sep 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants