Hide menu Last updated: Mar 02 2017
Area: Episerver Commerce Applies to versions: 10.2 and higher
Other versions:

Serializable carts

This topic describes the SerializedCarts model in Episerver Commerce. With this model, all cart data is stored in a single table, providing a fast and efficient way to load, update, and save cart information. 

How it works

In the SerializedCarts data model, all cart data is stored in one table, SerializableCart. This table contains these defined and searchable columns:

  • CartId
  • Created
  • Modified
  • Name
  • CustomerId

The table's last column is the Data column, where all the cart data is serialized to JSON format then stored as a string.

Serializable components

All cart data is serialized to a JSON formatted string before persisting it to the database. To achieve this, several cart components participate in the serialization/deserialization procedure. The following components are used:

  • SerializableCart (inherits from ICart)
  • SerializableLineItem (inherits from ILineItem)
  • SerializableNote (inherits from IOrderNote)
  • SerializableOrderAddress (inherits from IOrderAddress)
  • SerializableOrderForm (inherits from IOrderForm)
  • SerializablePayment (inherits from IPayment)
  • SerializableShipment (inherits from IShipment)

Consequently, a custom JSON converter (which inherits from JsonConverter) is needed for each new component.

  • SerializableLineItemConverter
  • SerializableNoteConverter
  • SerializableOrderAddressConverter
  • SerializableFormConverter
  • SerializablePaymentConverter
  • SerializableShipmentConverter

Note: All components and custom json converters are internal, which means that the classes support the Episerver infrastructure, and are not intended to be used directly from your code.

Order factory interface

This serializable cart system eliminates any relations to MetaDataPlus (MetaObject) (used in legacy versions). Therefore, when creating cart components (such as order form, shipment, line item, and so on), the system needs a factory that is different from the one used for purchase orders and payment plans.

The legacy system uses IOrderFactory for all carts (ICart), purchase orders (IPurchaseOrder) and payment plans (IPaymentPlan).

The IOrderFactory interface is now obsoleted. The SerializedCarts data model introduces new ways to create components that work in both legacy systems and new system:

  • IOrderGroupBuilder. Used to create sub-components for IOrderGroup. A builder is registered to create sub-components for a collection of type order group (see ForType property). A builder also has a SortOrder. If there are multiple registered builders for a type, the one with the highest sort order value is chosen.
  • IOrderGroupFactory. Responsible for creating instances of order group components by using IOrderGroupBuilder. The default implementation automatically registers all builders for all types of IOrderGroup.

Extension methods for IOrderGroup were also added for creating components by using IOrderGroupFactory. The following example shows usage. 

cart.AddLineItem(OrderFactory.CreateLineItem(code), OrderFactory); // old way
cart.AddLineItem(cart.CreateLineItem(code, OrderGroupFactory), OrderGroupFactory) // new way

See the latest Episerver Commerce QuickSilver sample site for an example of using IOrderGroupFactory.

Inventory information

In legacy versions, inventory information was wrapped in the concrete classes LineItem and Shipment. Since that information is needed for new carts, these now exist in separate interfaces:

  • ILineItemInventory. Contains the following inventory information for a line item:
    • Code
    • AllowBackordersAndPreorders
    • InStockQuantity
    • BackorderQuantity
    • PreorderQuantity
    • InventoryStatus
    • MaxQuantity
    • MinQuantity
  • IShipmentInventory. Handles inventory operation keys for a shipment.

IShippingPlugin and IPaymentPlugin

To work with the new mode, you need to migrate all custom implementations of IShippingGateway and IPaymentGateway / ISplitPaymentGateway to IShippingPlugin and IPaymentPlugin / ISplitPaymentPlugin. The new interfaces use IShipment instead of Shipment and IPayment instead of Payment.

Note: The implementation of IShippingGateway and IShippingPlugin requires a constructor which takes IMarket as a parameter.

Enabling SerializedCarts

By default, the SerializedCarts mode is enabled for a new installation site and disabled for an upgraded site.

To enable SerializedCarts mode, do the following:

  1. Edit the ecf.app.config file.
  2. Go to the Features section.
  3. Change the SerializedCarts setting from Disabled to Enabled.

If that setting does not exist, add it like this:

<add feature="SerializedCarts" state="Enabled" type="Mediachase.Commerce.Core.Features.SerializedCarts, Mediachase.Commerce" />

Alternatively, enable the SerializedCarts mode programmatically by adding the following to your InitializeModule class:

ServiceLocator.Current.GetInstance<IFeatureSwitch>().EnableFeature(SerializedCarts.FeatureSerializedCarts);

Migrating existing legacy carts

If switching from a legacy version to Serializable carts, you may need to migrate existing carts. If so, run the scheduled job LegacyCartsMigrationJob (available in the CMS admin view), right after switching to the new cart system to complete the migration and remove legacy carts.

Note: You should run the scheduled job directly after switching to serializable carts. After migrating legacy carts, the job is no longer visible in CMS admin view.

Comments

Since it's all serialized to JSON, does this mean I can simply create my own POCO-class inheriting ICart to add new properties to the cart (and likewise for purchase orders, line items etc)..? No more meta field initialization etc..?

@Arve: This only works with ICart - for purchase orders it will still use the same tables as before. The point of new cart system is to allow you plug your custom implementation as you like it. However, if you use the default implementation, you'll have to stay with SerializableCart class and you'll have to use Properties property to work with extra fields. If you want to use POCO approach, then you will likely have to implement your own ICartProvider. 

Allrighty, thanks!

Has anybody done anything with reading data out from the table directly?  I know the data is stored in json format, but I need to be able to extract that out to a view that can be used for migrating data into another system.  I realize the structure of the table could change (that is a risk I am willing to live with), but I absolutely have to grab the data from the table and not from any API calling the data.

Hi Steven, you could use SerializableCartDB.Load to get a list of SerializableCart.

This could fit for your case but it isn't good approach because this class was internal and it could be changed also.