Catalog Domain Extension

I am trying to extend the Catalog domain, specifically to add a new string field called CatalogType to it. I am following the example documented here: Extensibility - Extending domain models - Virto Commerce Documentation but seem to have run into a roadblock.

A new database migration gets created successfully, and I see the new column on the Catalog table. When I go to the swagger docs, I see my new field show up on the schema.

However, when I call the GET /api/catalog/catalogs/{id} endpoint, the new field is not returned on the response object. And, when I POST to the /api/catalog/catalogs endpoint, and include a value for my new field in the body, the value for this field is not saved to the database.

I suspect that Iā€™ve missed something in my Module.cs file, but am not sure where I went wrong.At the bottom of the example, it mentions There is a technical task of an instantiation of the right ā€œeffectiveā€ type instance from incoming JSON data (deserialization)......... Use platform-defined PolymorphJsonConverter . It's preferable to use in most cases. The PolymorphJsonConverter transparently deserializes extended domain types with no developer effort. I read this as ā€˜do nothingā€™, but perhaps there is some code to be writen.

I have defined a new subclass derived from the original Catalog class

using VirtoCatalog = VirtoCommerce.CatalogModule.Core.Model.Catalog;

namespace DomainExtension.Catalog.Core.Models
{
    /// <summary>
    /// Custom extension of the existing Catalog object
    /// </summary>
    public class Catalog2: VirtoCatalog
    {

        /// <summary>
        /// type of catalog
        /// </summary>
        public string CatalogType { get; set; }

    }
}

I have derived my dbContext from the existing CatalogDbContext

public class DomainExtensionCatalogDbContext : CatalogDbContext
    {
        public DbSet<Catalog2Entity> Catalog2s { get; set; }

        public DomainExtensionCatalogDbContext(DbContextOptions<DomainExtensionCatalogDbContext> options)
          : base(options)
        {
        }

        protected DomainExtensionCatalogDbContext(DbContextOptions options)
            : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Catalog2Entity>();
            base.OnModelCreating(modelBuilder);
        }
    }

I have derived my repository class from the existing CatalogRepositoryImpl

public class Catalog2Repository: CatalogRepositoryImpl
    {
        /// <summary>
        /// default constructor
        /// </summary>
        /// <param name="dbContext">extended db context</param>
        public Catalog2Repository(DomainExtensionCatalogDbContext dbContext): base(dbContext)
        {

        }

        public IQueryable<Catalog2Entity> Catalogs2 => DbContext.Set<Catalog2Entity>();
    }

I have created the new persistence model

public class Catalog2Entity: CatalogEntity
    {
        /// <summary>
        /// property for the type of catalog
        /// </summary>
        [StringLength(128)]
        public string CatalogType { get; set; }

        public override VirtoCatalog ToModel(VirtoCatalog catalog)
        {
            if (catalog is Catalog2 catalog2)
            {
                catalog2.CatalogType = CatalogType;
            }

            base.ToModel(catalog);
            return catalog;
        }

        public override CatalogEntity FromModel(VirtoCatalog catalog, PrimaryKeyResolvingMap pkMap)
        {
            if(catalog is Catalog2 catalog2)
            {
                CatalogType = catalog2.CatalogType;
            }

            base.FromModel(catalog, pkMap);
            return this;
        }

        public override void Patch(CatalogEntity target)
        {
            if(target is Catalog2Entity target2)
            {
                target2.CatalogType = CatalogType;
            }

            base.Patch(target);
        }
    }

In the Module.cs file Iā€™ve added the following for overriding types in the PostInitialize method

AbstractTypeFactory<CatalogEntity>.OverrideType<CatalogEntity, Catalog2Entity>();
AbstractTypeFactory<VirtoCatalog>.OverrideType<VirtoCatalog, Catalog2>().WithFactory(() => new Catalog2());

And in the Initialize method Iā€™ve included

serviceCollection.AddTransient<ICatalogRepository, Catalog2Repository>();

My question is: Where did I go wrong? What am I missing so that I may use the existing API endpoints and have them recognize my extended catalog type.

Thank you in advance!

1 Like

Does your swagger schema contain a new field?

Please check two things:

1 Like

Yes, the swagger schema shows my new field.

I have indeed registered my custom DbContext and repository in DI.

            // initialize DB
            serviceCollection.AddDbContext<DomainExtensionCatalogDbContext>((provider, options) =>
           {
               var configuration = provider.GetRequiredService<IConfiguration>();
               options.UseSqlServer(configuration.GetConnectionString(ModuleInfo.Id) ?? configuration.GetConnectionString("VirtoCommerce"));
           });

            serviceCollection.AddTransient<ICatalogRepository, Catalog2Repository>();

However, I did not have a discriminator, so I just added this to my migration, with the default Catalog2Entity value.

I am still having the same issue after doing this. Thank you both so much for your suggestions thus far. I appreciate your time.

The last thing you could check is that you have added the CatalogModule dependency to your module.manifest. This dependency is mandatory because it controls the order in which the modules are initialized.
If that doesnā€™t help, could you please share the code of your extension module with us? You can use the Gitter channel VirtoCommerce/vc-platform - Gitter and send a link to the code to me privately @tatarincev.

That was it. I had a typo and had the CustomerModule in there as a dependency instead :cry: . Thank you so much for your continued help. All is working now.

2 Likes