Commerce Foundation Operation Sequences

A Microsoft Multi-Channel Commerce Foundation operation sequence is a chain of one or more components (operation sequence components), forming a commerce operation which acts on a CommerceEntity of a particular model (as specified by a commerce request).

Commerce Server 2009 R2 controls the execution of the operation through the operation sequence. The operation sequence determines the order in which to apply each component to process a given operation. Each operation sequence component implements an interface.

Dd442376.4f0878d5-9a46-4e98-8223-9d843b528086(en-us,CS.95).gif

This topic covers the following:

  • Understanding Sequence Component Interfaces

  • Creating an Operation Sequence Component

  • Configuring a Commerce Foundation Operation Sequence

For information about adding auditing capability to custom operation sequences, see Commerce Foundation Auditing.

Understanding Sequence Component Interfaces

An operation sequence is comprised of components, and each component implements an interface. Commerce Server 2009 R2 predefines the following four operation sequence component interfaces:

  • IPreprocessSequenceComponent

  • ICommerceAuthorizableSequenceComponent

  • IOperationSequenceComponent

  • IPostProcessSequenceComponent

IPreprocessSequenceComponent

During an operation sequence, the IPreprocessSequenceComponent is the first sequence component interface called by the operation service if implemented. The operation service executes all those components in the sequence that implement the IPreprocessSequenceComponent in the order in which the components appear in the channel configuration file. For more information about the order in which the operation service calls sequence component interfaces, see Operation Service Interpretation of the Operation Sequence.

Since it is the first interface called, you may want to use this interface to prepare an environment for the rest of the components in the operation sequence. For example, if several components require a common resource, you could use the IPreprocessSequenceComponent interface to get the common resource and put it in the cache.

The IPreprocessSequenceComponent exposes two methods: Preprocess and Preauthorize. Both methods perform the same function. They differ only in the context in which they run. The former runs in the context of a ProcessRequest call to operation service, while the latter runs in the context of an AuthorizeRequest call to the operation service.

To create a component that implements the IPreprocessSequenceComponent interface, you must implement the interface defined below:

public interface IPreprocessSequenceComponent
{
   void Preprocess( CommerceOperation operation, 
                 OperationCacheDictionary operationCache, 
                 CommerceOperationResponse response);

   void Preauthorize(CommerceAuthorizationOperation operation, 
                     OperationCacheDictionary operationCache, 
                     CommerceAuthorizationOperationResponse response);

For information about creating a sequence component with this interface, see Creating an Operation Sequence Component.

ICommerceAuthorizableSequenceComponent

During an operation sequence, the ICommerceAuthorizableSequenceComponent is the second sequence component interface called by the operation service if implemented. The operation service executes all those components in the sequence that implement the ICommerceAuthorizableSequenceComponent in the order in which the components appear in the channel configuration file. For more information about the order in which the operation service calls sequence component interfaces, see Operation Service Interpretation of the Operation Sequence.

You use this interface to ensure that the current identity is allowed to perform the requested operation on the specified channel, entity, properties, and relationships. For example, you could use the ICommerceAuthorizableSequenceComponent to verify that a user is allowed to update all product properties except price on your Web site.

The ICommerceAuthorizableSequenceComponent exposes two methods: CanExecute and AuthorizeOperation. The former runs in the context of a ProcessRequest call to operation service, while the latter runs in the context of an AuthorizeRequest call to the operation service.

If a component implements the ICommerceAuthorizableSequenceComponent.CanExecute interface method as part of a ProcessRequest call to the operation service, the component compares the collection of claims associated with the current identity against the claims specified in MetadataDefinitions.xml for the requested channel, entity, operation. The component returns a "true" or "false" response if the claims do or do not match. If all the components that implement ICommerceAuthorizableSequenceComponent.CanExecute interface method return a "true" response, then the operation service calls those components that implement the IOperationSequenceComponent.Execute interface method to perform the requested operation. If any component returns a "false" response, the operation service terminates the operation sequence and throws an exception.

If a component implements the ICommerceAuthorizableSequenceComponent.AuthorizeOperation interface method as part of an AuthorizeRequest call to the operation service, the component requests the operation service to look in MetadataDefinitions.xml for the claims required to perform the specified operation on the requested channel, entity, and properties. The operation service returns the list of claims to the component making the request.

To create a component that implements the ICommerceAuthorizableSequenceComponent interface, you must implement the interface defined below:

public interface ICommerceAuthorizableSequenceComponent
{
   void AuthorizeOperation(CommerceAuthorizationOperation operation, 
                           OperationCacheDictionary operationCache, 
                           CommerceAuthorizationOperationResponse response);

   bool CanExecute(CommerceOperation operation, 
                   List<CommerceAccessViolation> errors);
}

For information about creating a sequence component with this interface, see Creating an Operation Sequence Component.

IOperationSequenceComponent

During an operation sequence, the IOperationSequenceComponent is the third sequence component interface called by the operation service during a ProcessRequest. The operation service executes all those components in the sequence that implement the IOperationSequenceComponent in the order in which the components appear in the channel configuration file. For more information about the order in which the operation service calls sequence component interfaces, see Operation Service Interpretation of the Operation Sequence.

The IOperationSequenceComponent exposes only one method: Execute. This method runs in the context of a ProcessRequest call to operation service.

To create a component that implements the IOperationSequenceComponent interface, you must implement the interface defined below:

public interface IOperationSequenceComponent 
{
   void Execute( CommerceOperation operation, 
                 OperationCacheDictionary operationCache, 
                 CommerceOperationResponse response);
}

Alternatively, you can create an operation sequence component that simply inherits from the OperationSequenceComponent base class. This provides strongly typed operation methods along with all of the necessary tracing capabilities.

Dd442376.11c2a851-81ca-4f36-af70-14b336996407(en-us,CS.95).gif

For information about creating a sequence component with this interface, see Creating an Operation Sequence Component.

IPostProcessSequenceComponent

During an operation sequence, the IPostProcessSequenceComponent is the last sequence component interface called by the operation service if implemented. The operation service executes all those components in the sequence that implement the IPostProcessSequenceComponent in the order in which the components appear in the channel configuration file. For more information about the order in which the operation service calls sequence component interfaces, see Operation Service Interpretation of the Operation Sequence.

Since it is the last interface called, this interface is useful to perform post process cleanup. For example, you could use the IPostProcessSequenceComponent interface to free resources, commit information to the database, or build a response object.

The IPostProcessSequenceComponent exposes two methods: PostProcess and PostAuthorize. Both methods perform the same function. They differ only in the context in which they run. The former runs in the context of a ProcessRequest call to operation service, while the latter runs in the context of an AuthorizeRequest call to the operation service.

If an error occurs during the execution of the IOperationSequenceComponent.Execute interface method or ICommerceAuthorizableSequenceComponent.AuthorizeOperation interface method, the operation service catches the exception. The operation service then calls IPostProcessSequenceComponent.PostProcess or IPostProcessSequenceComponent.PostAuthorize interface method and passes the exception. If no error occurs during the execution of the IOperationSequenceComponent.Execute phase or ICommerceAuthorizableSequenceComponent.AuthorizeOperation phase, the processingError parameter for the PostProcess or PostAuthorize method is null to signify no errors have occurred.

To create a component that implements the IPostProcessSequenceComponent interface, you must implement the interface defined below:

    /// <summary>
    /// Post Process Sequence Component Interface.
    /// Components implementing this interface are executed after all other components.
    /// </summary>
    public interface IPostProcessSequenceComponent
    {
        /// <summary>
        /// Postprocess method for an operation sequence component
        /// </summary>
        /// <param name="operation">The operation</param>
        /// <param name="operationCache">The operation cache</param>
        /// <param name="response">The response</param>
        /// <param name="processingError">The error, if one occured during the Execution(Execute) of this sequence</param>
        void PostProcess(CommerceOperation operation, OperationCacheDictionary operationCache, CommerceOperationResponse response, Exception processingError);

        /// <summary>
        /// PostAuthorize method for an operation sequence component
        /// </summary>
        /// <param name="operation">The authorization operation</param>
        /// <param name="operationCache">The operation cache</param>
        /// <param name="response">The response</param>
        /// <param name="processingError">The error, if one occured during the Authorization(Authorize) of this sequence</param>
        void PostAuthorize(CommerceAuthorizationOperation operation, OperationCacheDictionary operationCache, CommerceAuthorizationOperationResponse response, Exception processingError);
    }
}

For information about creating a sequence component with this interface, see Creating an Operation Sequence Component.

Creating an Operation Sequence Component

To create a sequence component, you must implement one of the defined sequence component interfaces. The interface and method you implement for each component depends on many factors:

  • The method used to call the operation service (ProcessRequest or AuthorizeRequest).

  • The tasks you want to accomplish within the operation sequence.

  • The order in which the tasks must be accomplished.

During the processing of an operation sequence, the operation service calls component interfaces in a specific order. For a ProcessRequest, the operation service calls the following component interfaces and methods in the order shown below:

  1. IPreprocessSequenceComponent : Preprocess

  2. ICommerceAuthorizableSequenceComponent : CanExecute

  3. IOperationSequenceComponent : Execute

  4. IPostProcessSequenceComponent : PostProcess

Whereas for an AuthorizeRequest, the operation service calls the following sequence component interfaces and methods in the following order:

  1. IPreprocessSequenceComponent : Preauthorize

  2. ICommerceAuthorizableSequenceComponent : AuthorizeOperation

  3. IPostProcessSequenceComponent : PostAuthorize

For more information about the order in which the operation service calls sequence component interfaces, see Operation Service Interpretation of the Operation Sequence.

The Microsoft Multi-Channel Commerce Foundation defines the following interfaces for creating a sequence component:

Interface name

Interface

IPreprocessSequenceComponent

public interface IPreprocessSequenceComponent
{
   void Preprocess( CommerceOperation operation, 
                 OperationCacheDictionary operationCache, 
                 CommerceOperationResponse response);
   void Preauthorize(CommerceAuthorizationOperation operation, 
                     OperationCacheDictionary operationCache, 
                     CommerceAuthorizationOperationResponse response);
}

ICommerceAuthorizableSequenceComponent

public interface ICommerceAuthorizableSequenceComponent
{
   void AuthorizeOperation(CommerceAuthorizationOperation operation, 
                           OperationCacheDictionary operationCache, 
                           CommerceAuthorizationOperationResponse response);
   bool CanExecute(CommerceOperation operation, 
                   List<CommerceAccessViolation> errors);
}

IOperationSequenceComponent

public interface IOperationSequenceComponent 
{
   void Execute( CommerceOperation operation, 
                 OperationCacheDictionary operationCache, 
                 CommerceOperationResponse response);
}

IPostProcessSequenceComponent

public interface IPostProcessSequenceComponent
{
    void PostProcess(CommerceOperation operation, OperationCacheDictionary operationCache, CommerceOperationResponse response, Exception processingError);
    void PostAuthorize(CommerceAuthorizationOperation operation, OperationCacheDictionary operationCache, CommerceAuthorizationOperationResponse response, Exception processingError);
}

Following is an example of a sequence component that uses the IOperationSequenceComponent interface for a QueryOperation:

public class MyOperationSequenceComponent : IOperationSequenceComponent

{
    public void Execute(
        Microsoft.Commerce.Operation operation, 
        OperationCacheDictionary operationCache, 
        Microsoft.Commerce.OperationResponse response)
    {
        if ( operation is QueryOperation )
        {
            // Do something...
        }
    }
}

Instead of using the IOperationSequenceComponent interface, you can choose to create an operation sequence component that simply inherits from the OperationSequenceComponent base class instead. This provides strongly typed operation methods with all of the necessary tracing capabilities.

Dd442376.11c2a851-81ca-4f36-af70-14b336996407(en-us,CS.95).gif

Follwoing is an example of a sequence component for a QueryOperation that inherits from the OperationSequenceComponent base class:

public class MyOperationSequenceComponent : OperationSequenceComponent
{
    public override void ExecuteQuery(
          CommerceQueryOperation queryOperation,
          OperationCacheDictionary operationCache, 
          CommerceQueryOperationResponse response)
    {
        // Do Something
    }
}

The following table describes the parameters shared by all the sequence component interfaces:

Parameter

Description

operation

Represents the current operation being processed by the operation service.

operationCache

The operationCache is a string-to-object dictionary that can be used in a manner similar to how the ASP.NET Cache is used. Only, it does not store objects between operation invocations, but rather between the invocations of the components that belong to the same operation.

This cache object allows the Microsoft Multi-Channel Commerce Foundation operation sequence components to share expensive resources during the operation execution. For example, in the product query scenario the ProductLoader retrieves one or more products from the Commerce Server database and translates them into the Commerce Server 2009 R2 products that become part of the operation response. After the operation sequence component finishes its job, it stores the retrieved Commerce Server products in the Cache. This enables a subsequent operation sequence components to easily retrieve these Commerce Server products from the cache rather than from Commerce Server to perform its specific task - for example supplying the product cross-sell or up-sell or variants etc.

response

Response object passed to each component. The response object is created by the Server based on the responseType configuration attribute.

Configuring a Commerce Foundation Operation Sequence

A Microsoft Multi-Channel Commerce Foundation operation can have any number of sequence components defined for the operation sequence. You can customize the business rules of an operation simply by manipulating the content of the operation sequence by either replacing components or adding your own.

All the components in an operation sequence can be replaced and any number of components can be added to it. However, you must implement the appropriate sequence component interface to engage in the operation at the correct time to successfully process a request.

For more information about the order in which the operation service calls sequence component interfaces, see Operation Service Interpretation of the Operation Sequence.

Following is an example of the configuration section that defines a Microsoft Multi-Channel Commerce Foundation operation. The configuration sections reflect the object model described above. A MessageHandler contains the OperationSequence that consists of one or more components defined in a sequential order.

<MessageHandler name="CommerceQueryOperation_Product"
   responseType="Microsoft.Commerce.CommerceQueryOperationResponse, Microsoft.Commerce, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35">
      <OperationSequence>
         <Component name="Authorization" type="Microsoft.Commerce.SequenceComponents.Components.AuthorizationSequenceComponent, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
         <Component name="ProductConfiguration_Prepare" type="Microsoft.Commerce.SequenceComponents.Components.ProductPrepareQuery, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35" >
         <Component name="Product Query Processor" type="Microsoft.Commerce.SequenceComponents.Components.ProductLoader, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
         <Component name="Cross-Sell Provider" type="Microsoft.Commerce.SequenceComponents.Components.ProductCommerceServerRelationshipProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35">
            <Configuration
               customElementName="CommerceServerRelationshipConfiguration"
               customElementType="Microsoft.Commerce.SequenceComponents.Components.CommerceServerRelationshipConfiguration, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35">
               <CommerceServerRelationshipConfiguration commerceServerRelationshipName="CrossSell" internalRelationshipName="CrossSells"/>
            </Configuration>
         </Component>
         <Component name="Up-Sell Provider" type="Microsoft.Commerce.SequenceComponents.Components.ProductCommerceServerRelationshipProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35">
            <Configuration
               customElementName="CommerceServerRelationshipConfiguration"
               customElementType="Microsoft.Commerce.SequenceComponents.Components.CommerceServerRelationshipConfiguration, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35">
               <CommerceServerRelationshipConfiguration commerceServerRelationshipName="UpSell" internalRelationshipName="UpSells"/>
            </Configuration>
         </Component>
         <Component name="Product Variant Processor" type="Microsoft.Commerce.SequenceComponents.Components.ProductVariantProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
         <Component name="ProductAncestorCategoryProcessor" type="Microsoft.Commerce.SequenceComponents.Components.ProductAncestorCategoryProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
         <Component name="ProductCanonicalCategoryProcessor" type="Microsoft.Commerce.SequenceComponents.Components.ProductCanonicalCategoryProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
         <Component name="ProductParentCategoryProcessor" type="Microsoft.Commerce.SequenceComponents.Components.ProductParentCategoryProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
         <Component name="ProductPrimaryCategoryProcessor" type="Microsoft.Commerce.SequenceComponents.Components.ProductPrimaryCategoryProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
         <Component name="ProductRelatedCategoryProcessor" type="Microsoft.Commerce.SequenceComponents.Components.ProductRelatedCategoryProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
         <Component name="ProductRelatedProductProcessor" type="Microsoft.Commerce.SequenceComponents.Components.ProductRelatedProductProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
         <Component name="ProductInventoryItemsProcessor" type="Microsoft.Commerce.SequenceComponents.Components.ProductInventoryItemsProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
         <Component name="Product catalog relationship" type="Microsoft.Commerce.SequenceComponents.Components.ProductCatalogRelationshipProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
         <Component name="Product base catalog relationship" type="Microsoft.Commerce.SequenceComponents.Components.ProductBaseCatalogRelationshipProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
         <Component name="Product Discounts Relationship" type="Microsoft.Commerce.SequenceComponents.Components.CatalogEntityDiscountsProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35" />
         <Component name="Product Image Relationship Processor" type="Microsoft.Commerce.SequenceComponents.Components.ProductImageRelationshipProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35" componentConfiguration="CommerceImageCatalogConfiguration" />
         <Component name="Product Variant Image Relationship Processor" type="Microsoft.Commerce.SequenceComponents.Components.ProductVariantImageRelationshipProcessor, Microsoft.Commerce.SequenceComponents, Version=9.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35" componentConfiguration="CommerceImageCatalogConfiguration" />
      </Component>
   </OperationSequence>
</MessageHandler>

In the MessageHandler element, the name attribute maps an incoming operation request to the appropriate Microsoft Multi-Channel Commerce Foundation operation sequence, whose component classes process the request and generate the response. The name of a Microsoft Multi-Channel Commerce Foundation MessageHandler consists of two parts separated by an underscore character. The first part is the name of the operation type and the second part is the model name of the commerce entity upon which the operation is performed.

The name of the operation is obtained from the Name property of the Type object for the operation of the request. This name is stripped of any namespace information. This allows you to use the same configuration sections for the operations that handle the requests that are based on the classes derived from the operation as long as the name are the same as the Microsoft Multi-Channel Commerce Foundation class. The namespace of course should be different from the Microsoft Multi-Channel Commerce Foundation namespace. However, if you decide to use different names for the derived types you will have to change the MessageHandler names in the configuration file.

The Component can be expressed as a hierarchy that represents the dependencies between the components. In the example shown, all components depend on the Product Query Processor component.

The following are the MessageHandler element attributes:

Attribute

Description

responseType

Tells the server which response class to instantiate via reflection. The response is always created by the server and updated by the operation sequence components.

name

Identifies the operation and commerce element handled by the message handler.

The following are the OperationSequence element attributes:

Attribute

Description

Transactional

Indicates whether the operation sequence is transactional.

TransactionIsolationLevel

Specifies the isolation level for the operation sequence transaction. Valid values include Serializable, RepeatableRead, ReadCommitted, ReadUncommitted, Snapshot, Chaos, and Unspecified.

TransactionTimeout

Specifies the time out for the operation sequence transaction.

The following are the Component element attributes:

Attribute

Description

name

The name attribute is a short name given to the operation sequence component. It must be unique across all operation sequence components of the operation.

description

The description attribute is only intended for human consumption and is used to improve the readability of the operation configuration.

type

The most important attribute of the Component element is type. It fully defines the type of the corresponding component. Commerce Server 2009 R2 uses its value to dynamically instantiate the component through the reflection mechanism. The type attribute format follows the standard .NET way to specify a class type in the configuration file. It should contain comma separated strings. The first string is a fully qualified name of the class that is prefixed with all the namespaces. The second one is the name of the containing assembly, optionally followed by the assembly version, the culture and the public key token.

TransactionScopeOption

Indicates the transaction scope. The options are:

OptionDescription
None (default)No transaction support is defined or created.
RequiredParticipates in the existing transaction. If no transaction is present, a new transaction will be created.
RequiresNewThe component executes within a new transactional scope.
SuppressThe component executes in a non-transactional scope.

TransactionIsolationLevel

Specifies the isolation level for the operation sequence transaction. Valid values include Serializable, RepeatableRead, ReadCommitted, ReadUncommitted, Snapshot, Chaos, and Unspecified.

TransactionTimeout

Specifies the time out for the component transaction.

The following table lists the Configuration element attributes:

Attribute

Description

customElementName

The name of the XML element that contains configuration for the operation sequence component. An XML element with this name must be a child of the Component element.

customElementType

The ConfigurationElement type used to load the configuration of the operation sequence component.

The classes specified through the type attribute of the Component element must implement the proper interface described above. If the types registered as components in the Operation section fail to implement the proper interface, the InvalidCastException is thrown during runtime. Every operation component must have a public default (parameterless) constructor.

In This Section

See Also

Other Resources

Developing with the Multi-Channel Commerce Foundation

Commerce Foundation Transactions

Commerce Foundation Operation Sequence Extensibility Point