Importing to inRiver PMC

Setting up Avensia Storefront inRiver PMC import

Data is imported to inRiver PMC from Avensia Storefront Staging by setting up an Avensia Storefront Pipeline with Transformers and Writers that write entity data to PMC. The framework for this is included in the Avensia.Storefront.InriverPmc.Import package.

 

Setting up the model

For each entity that should be imported to inRiver PMC, an Entity Definition Model needs to be added that includes the fields that should be imported for that entity. The definition model should inherit from the BaseEntity class. Example of a Product Entity definition model:

public class Product : BaseEntity
{
  public string Name { get; set; }
  public bool SomeBooleanField { get; set; }
  public int SomeIntegerField { get; set; }
  public string SomeStringField { get; set; }
}

 

Setting up the pipeline

In your bootstrapper, register a module set consumer with a pipeline task for each staging DTO that should be processed.

Use your Entity Definition Models as input types to the transformers and writers where needed - in the example below, Product, Item, ProductKit and Resource are entity definition models. Use patchers to modify your data fields as needed - for one-to-one-mapping the supplied automapping-patchers can be used.

A complete pipeline setup can look something like this:

moduleRegistration.RegisterModuleSetConsumer(
  ImportModules.Catalog,
    m =>
      {
        m.AddMultiLanguagePipelineTask<ProductDto, ProductWithItems<Product, Item>>(
            task =>
                {
                    task.Name("Product");
                    task.UseReader<ProductReader<ProductDto>>();
                    task.UseTransformer<ProductTransformer<ProductDto, Product, Item>>();
                    task.AddPatcher<ProductAutoMappingPatcher<ProductDto, Product, Item>>();
                    task.AddPatcher<ItemAutoMappingPatcher<ProductDto, Product, Item>>();
                    task.UseWriter<ProductWriter<ProductDto, Product, Item>>();
                });

        m.AddMultiLanguagePipelineTask<ProductKitDto, ProductKit>(
            task =>
                {
                    task.Name("Product Kit");
                    task.UseReader<ProductKitReader>();
                    task.UseTransformer<ProductKitTransformer<ProductKitDto, ProductKit>>();
                    task.UseWriter<ProductKitWriter<ProductKitDto, ProductKit>>();
                });

        m.AddPipelineTask<EntryMediaDto, ResourceEntryToSave<Product, Resource>>(
            task =>
                {
                    task.Name("Product Media");
                    task.UseReader<ProductMediaReader>();
                    task.UseTransformer<ProductMediaTransformer<EntryMediaDto, Product, Resource>>();
                    task.UseWriter<ProductMediaWriter<EntryMediaDto, Product, Resource>>();
                });

        m.AddPipelineTask<EntryMediaDto, ResourceEntryToSave<Item, Resource>>(
            task =>
                {
                    task.Name("Item Media");
                    task.UseReader<VariationMediaReader>();
                    task.UseTransformer<ItemMediaTransformer<EntryMediaDto, Item, Resource>>();
                    task.UseWriter<ItemMediaWriter<EntryMediaDto, Item, Resource>>();
                });

        m.AddPipelineTask<EntryMediaDto, ResourceEntryToSave<ProductKit, Resource>>(
            task =>
                {
                    task.Name("Product Kit Media");
                    task.UseReader<ProductKitMediaReader>();
                    task.UseTransformer<ProductKitMediaTransformer<EntryMediaDto, ProductKit, Resource>>();
                    task.UseWriter<ProductKitMediaWriter<EntryMediaDto, ProductKit, Resource>>();
                });

        m.AddPipelineTask<ProductDeletionDto, ProductWithItems<Product, Item>>(
            task =>
                {
                    task.Name("Product Deletion");
                    task.UseReader<ProductDeletionReader>();
                    task.UseTransformer<ProductDeletionTransformer<ProductDeletionDto, Product, Item>>();
                    task.UseWriter<ProductDeletionWriter<ProductDeletionDto, Product, Item>>();
                });
        });

 

Setting up custom target PMC entity type names

By default, the import expects the entity types in PMC to have these names: Product, Item, Resource, ProductKit and ProductKitGroup. The link type names should use the standard SourceTarget-pattern, that is, the Product -> Item link should be named ProductItem. If the PMC model have different names for the entity types or link types, this needs to be configured by overriding the class PmcConfiguration and provide overridden EntityTypes and LinkTypes for the types that is not default. Example:

public class CustomPmcConfiguration : PmcConfiguration
{
    public CustomPmcConfiguration(IinRiverManager inRiverManager) : base(inRiverManager)
    {
    }

    public override EntityType ProductEntityType => GetEntityType("MyProductEntityName");
    public override EntityType ItemEntityType => GetEntityType("MyItemEntityName");
    public override LinkType ProductItemLinkType => GetLinkType("MyProductToItemLinkName");        
}

The overridden PmcConfiguration then needs to be registered as a project dependency, example:

public class CustomProjectDependencyRegistration : Avensia.Storefront.Connector.InriverPmc.Import.ProjectDependencyRegistration
{
... public override void RegisterDependenciesInModuleContainer(RegistrationContext context) { base.RegisterDependenciesInModuleContainer(context); context.ConfigurationExpression.For(<IPmcConfiguration>).Use(<CustomPmcConfiguration>); } }

 

Creating your own EntityProcessingAttribute

To override the default handling of attributes, it is possible to add your own EntityProcessingAttribute that defines how to handle a specific field. The entity processing attribute implementation should include two methods, Map and Flush.


Map defines how the PMC entity field value should be written to your entity definition model field.


Flush, defines how the value of the entity definition model field should be written to the PMC entity field.

Example:

public class HelloAttribute : EntityProcessingAttribute
{
    public override void Flush(IContainer container, Field field, object value, CultureInfo cultureInfo)
    {
        field.Data = "Hello " + value as string;
    }

    public override object Map(IContainer container, Field field, CultureInfo cultureInfo)
    {
        return (field.Data as string)?.Substring("Hello ".Length);
    }
}

To use your new processing attribute, decorate the field in your entity definition model with the attribute:

public class Product : BaseEntity
{
  ...
  [Hello]
  public string Greeting { get; set; }
  ...
}

 

CVL attributes

An entity processing attribute for handling automatic addition of CVL values is included: AddCvlValueAttribute. By decorating a field in your entity definition model with this, the value will be used as key in a CVL field in PMC. If the key doesn't exist, it will be created with the same (normalized) name as the default language value.

 

Configuration

The PMC configuration is setup in a separate config section, which needs to be added to the configSections in app.config or web.config:

<configSections>
...
<section name="storefront.pmc" type="Avensia.Storefront.Connector.InriverPmc.Configuration.PmcConfigurationSection, Avensia.Storefront.Connector.InriverPmc.Configuration, Version=1.0.0, Culture=neutral" />
...
</configSections>

In the configsection, the PMC import settings are set on the outbound element:

<storefront.pmc>
    <outbound
        settingname1=value
        settingname2=value
        ...
    />
</storefront.pmc>

Settings

Setting nameDescription
url Url to the inRiver PMC endpoint
environment inRiver PMC environment (typically test or prod, or some sandbox during development)
username Username for access to inRiver PMC
password Password for access to inRiver PMC