Converting product sources into understandable products for Umbraco Commerce.
The role of a Product Adapter in Umbraco Commerce is to provide an interface between a product information source and convert it into a standardized format. This is done to prevent the need for Umbraco Commerce to be tied to that source.
What this means for developers is that Product Adapters allow you to hook in alternative product information sources that may not be Umbraco node-based. You may hold your product information in a third-party database table. A custom Product Adapter would then allow Umbraco Commerce to interface with that custom data in the same way it would the default Umbraco node data.
Example Product Adapter
An example of a Product Adapter would look something like this:
publicclassMyCustomProductAdapter:IProductAdapter{publicTask<IProductSnapshot> GetProductSnapshotAsync(string productReference,string languageIsoCode) { // Lookup a product by productReference and convert to IProductSnapshot }publicTask<IProductSnapshot> GetProductSnapshotAsync(string productReference,string productVariantReference,string languageIsoCode) { // Lookup a product by productVariantReference and convert to IProductSnapshot }Task<Attempt<(string ProductReference,string ProductVariantReference)>> TryGetProductReferenceAsync(Guid storeId,string sku) { // Try lookup a product / variant reference by store + sku }}
All Product Adapters implement the IProductAdapter interface which requires three method implementations:
Two GetProductSnapshotAsync methods that retrieve a Product Snapshot for either a product or product variant by reference parameters.
A TryGetProductReferenceAsync method which retrieves a product/variant reference for a product that belongs to a given storeId and has the given sku.
A Product Snapshot consists of the following properties in order to present a Product to Umbraco Commerce in a standard way.
publicinterfaceIProductSnapshot{ // The unique reference for the productstring ProductReference { get; } // The unique reference for the variant (if this is a variant snapshot)string ProductVariantReference { get; } // The unique SKU for this product/variantstring Sku { get; } // The name of this product/variantstring Name { get; } // The ID of the store this product/variant belongs toGuid StoreId { get; } // An optional Tax Class ID for this product/variantGuid? TaxClassId { get; } // Any properties exposed by this product/variant that should be copied to the orderlineIDictionary<string,string> Properties { get; } // Any variant attributes for this product (if this is a variant snapshot)IEnumerable<AttributeCombination> Attributes { get; } // The available prices for this product/variantIEnumerable<ProductPrice> Prices { get; } // Flag indicating whether this product is a gift card productbool IsGiftCard { get; }}
Support editable carts
To allow Umbraco Commerce to search for products/variants to add to a cart via the backoffice, Product Adapters can implement 3 additional methods. This can also be done to support editable carts.
publicclassMyCustomProductAdapter:ProductAdapterBase{ ... publicoverrideTask<PagedResult<IProductSummary>> SearchProductSummariesAsync(Guid storeId,string languageIsoCode,string searchTerm,long currentPage =1,long itemsPerPage =50) { // Search for products matching the given search term and convert to a IProductSummary }publicoverrideTask<IEnumerable<Attribute>> GetProductVariantAttributesAsync(Guid storeId,string productReference,string languageIsoCode) { // Lookup the in-use product attributes of a primary product }publicoverrideTask<PagedResult<IProductVariantSummary>> SearchProductVariantSummariesAsync(Guid storeId,string productReference,string languageIsoCode,string searchTerm,IDictionary<string,IEnumerable<string>> attributes,long currentPage =1,long itemsPerPage =50) { // Search for product variants matching the given search term and/or the given attributes and convert to a IProductVariantSummary }}
The IProductSummary, Attribute and IProductVariantSummary consists of the following properties in order to present a Product to Umbraco Commerce in a standard way.
publicinterfaceIProductSnapshot{ // The unique reference for the productstring Reference { get; } // The unique SKU for this product string Sku { get; } // The name of this product string Name { get; } // The available prices for this product IEnumerable<ProductPrice> Prices { get; } // Flag indicating whether this product has variantsbool HasVariants { get; }}publicclassAttribute{ // The alias of the attributepublicstring Alias { get; } // The name of the attributepublicstring Name { get; } // The attribute valuesIEnumerable<AttributeValue> Values { get; }}publicclassAttributeValue{ // The alias of the attribute valuepublicstring Alias { get; } // The name of the attribute valuepublicstring Name { get; }}publicinterfaceIProductVariantSnapshot{ // The unique reference for the product variantstring Reference { get; } // The unique SKU for this product variantstring Sku { get; } // The name of this product variantstring Name { get; } // The available prices for this product variantIEnumerable<ProductPrice> Prices { get; } // The collection of attribute alias pairs of this product variantIReadOnlyDictionary<string,string> Attributes { get; }}
Registering a Product Adapter
typeProduct Adapters are registered via the IUmbracoCommerceBuilder interface using the AddUnique<IProductAdapter, TReplacementAdapter>() method on the Services property. The TReplacementAdapter parameter is the type of our custom Product Adapter implementation.
publicstaticclassUmbracoCommerceUmbracoBuilderExtensions{publicstaticIUmbracoCommerceBuilderAddMyServices(IUmbracoCommerceBuilder builder) { // Replacing the default Product Adapter implementationbuilder.Services.AddUnique<ProductAdapterBase,MyCustomProductAdapter>(); // Return the builder to continue the chainreturn builder; }}