This diagram is taken from the PDC 2008 session "Commerce Server - Mojave"
Overview
I included the above diagram because I think it help visualize where Operations and OperationSequences fit into the overall solution. Mojave provides CRUD type operations at the entity level through the implementation of operations. So, for example, when you want to retrieve products from Mojave you would call the "QueryOperation_Product" operation. You will inevitably find a need to create your own Operations based on constructs which don't directly relate to entities in Commerce Server. In some cases I am finding it useful to create operations in terms of Use Cases not simply Commerce Entities.
Business Problem
Information is stored in several disparate systems which is required by the web to provide a feature rich shopping experience. The decision was made not to create a series of night synchronizations to keep this information up to date. Instead, during the execute of a use case we need to get this information and store it in Commerce Server. Then as the customer continues to browse the site, calls for this information will go directly against Commerce Server.
Solution
There are a couple of ways this solution could be implemented with Mojave. The first would be to create a series of operationsequences to perform CRUD operations against each disparate system. I think this would be good if you were going to be CRUD heavy to those systems. The second option would be to create a single operation sequence called "QueryOperation_UseCase". Then inside the QueryOperation, create a component for each call to the disparate systems. More often than not in a SOA enabled environment, you are calling a web service to perform an operation against a system and those operations aren't tied to direct CRUD operations on an entity. So for this solution we will follow option 2.
1. First, you need to create or update an existing Channel in the MetadataDefinitions.xml. If you are using the SampleSite available on the Connect site, you can update the "TestChannel". Add a CommerceEntity node for your Use Case (EntityName).
<CommerceEntity name="UseCase"></CommerceEntity>
2. Add a Channel child node to the Channels node in the ChannelConfiguration.config. The channel name is set to "TestChannel", the sitename is set to "SampleSite" based on SampleSite.pup, and the language is set to english.
3. Add a "MessageHandlers" child node to the Channel node then add a "MessageHandler" child node to the "MessageHandlers" node. In the "MessageHandler" node, set the name to "OperationQuery_UseCase". If this were a different operation type, you would set this appropriately. Set the "ResponseType" to the standard "QueryOperationResponse".
4. Add a "OperationPipeline" child node to the "MessageHandler" node then add a "Component" child node to the "OperationPipeline" node. In a previous blog article I talk about creating custom components.
<Channels> <Channel name="TestChannel" sitename="SampleSite" language="English"> <MessageHandlers> <MessageHandler name="QueryOperation_UseCase" responseType="Microsoft.Commerce.Contracts.Messages.QueryOperationResponse, Microsoft.Commerce.Contracts, Version=1.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"> <OperationPipeline> <Component name="DisparateSystemProvider" type="DisparateSystemMojaveLib.GetCustomerInfo, DisparateSystemMojaveLib, Version=1.0.0.0, Culture=neutral,PublicKeyToken=404bf9ce77dd9381" /> </OperationPipeline> </MessageHandler> </MessageHandlers> </Channel> </Channels>
5. Create the Custom component defined in the Component node above.
6. Create a class which inherits from CommerceEntity. Assign the ModelName to the UseCase. The class needs to be visible in the code which is going to call into the QueryOperation.
public class UseCase: CatalogEntity { /// <summary> /// Initializes a new instance of the <see cref="UseCase"/> class. /// </summary> public Login() : base() { this._commerceEntity = new CommerceEntity("UseCase"); }
public Login(CommerceEntity commerceEntity) : base(commerceEntity) { this._commerceEntity = commerceEntity; } }
7. Create the business logic to call the operation which executes the OperationalSequence.
// Create a Operation Service Agent OperationServiceAgent _operationService = new OperationServiceAgent();
// Query for a UseCase Query<UseCase> queryBuilder = new Query<UseCase>();
// Process the Request Response response = _operationService.ProcessRequest(Utility.CreateRequestContext(), queryBuilder.ToRequest()); QueryOperationResponse queryBuilderResponse = (QueryOperationResponse)response.OperationResponses[0];
UseCase UC= new UseCase(queryBuilderResponse.CommerceEntities[0]);
At this point you should be ready to test the solution.