Code Example: Running a Pipeline Outside a Web Application

For the latest version of Commerce Server 2007 Help, see the Microsoft Web site.

Example

The following code example runs the Basket pipeline, the Total pipeline, and the Checkout pipeline from a console application. For more information about the steps that you must follow to run a pipeline outside a Web application, see How to Run a Pipeline Outside a Web Application.

using System;
using System.Data;
using System.Data.Common;
using System.Collections;
using System.Globalization;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Data.OleDb;
using Microsoft.CommerceServer.Runtime;
using Microsoft.CommerceServer.Runtime.Pipelines;
using Microsoft.CommerceServer.Runtime.Configuration;
using Microsoft.CommerceServer.Runtime.Orders;
using Microsoft.CommerceServer.Internal.Marketing;
using Microsoft.CommerceServer.Interop;
using Microsoft.CommerceServer.Interop.Targeting;
using Microsoft.CommerceServer.Interop.Caching;
using Microsoft.CommerceServer.Catalog;
using Microsoft.CommerceServer.Orders;

namespace CS2007PipelineConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Starting the application.");
            OrderContext orderCtx = OrderContext.Create(Constants.SiteName);
            ConsolePipelineHelper pipeLineHelper = new ConsolePipelineHelper(Constants.SiteName, orderCtx);

            // Create a GUID for the user's ID, and then 
            // create a new Basket object.
            Guid userId = Guid.NewGuid();
            Basket basket = orderCtx.GetBasket(userId);

            Console.WriteLine("Populating the user's basket.");
            pipeLineHelper.PopulateCart(ref basket);

            // Create and run each of the three orders 
            // pipelines. 
            // You must have the pipeline files in the
            // "pipelines" subdirectory of the folder from
            // which you run this application.
            String pipelineDir = Environment.CurrentDirectory + @"\pipelines\";
            Console.WriteLine("Running the Basket pipeline.");
            pipeLineHelper.RunPipeline(basket, false, false, "Basket", pipelineDir + "basket.pcf");

            Console.WriteLine("Running the Total pipeline.");
            pipeLineHelper.RunPipeline(basket, false, false, "Total", pipelineDir + "total.pcf");

            Console.WriteLine("Running the Checkout pipeline.");
            pipeLineHelper.RunPipeline(basket, true, false, "Checkout", pipelineDir + "checkout.pcf");

            // Save the basket as a completed order.
            Console.WriteLine("Saving the order.");
            PurchaseOrder order = basket.SaveAsOrder();

            Console.WriteLine("Application completed!");
            Console.ReadLine();
        }
    }

    class ConsolePipelineHelper
    {
        PipelineInfo basketPipe, totalPipe, checkoutPipe;
        CommerceResourceCollection resources;
        bool catalogContextCreated = false;
        String webSiteName;
        CatalogContext catalogContext;
        OrderContext orderCtx;

        public ConsolePipelineHelper(String siteName, OrderContext orderContext)
        {
            resources = new CommerceResourceCollection(siteName);
            webSiteName = siteName;
            orderCtx = orderContext;
        }

        public String SiteName
        {
            get
            {
                return webSiteName;
            }
            set
            {
                webSiteName = (String)value;
            }
        }

        public void PopulateCart(ref Basket basket)
        {
            // Add an address to the basket.
            String addressId = Guid.NewGuid().ToString();
            OrderAddress addr = new OrderAddress("HomeAddress", addressId);
            basket.Addresses.Add(addr);

            // Add an order form to the basket.
            basket.OrderForms.Add(new OrderForm("MainOrderForm"));

            //Add an item to the basket.
            LineItem buyItem = new LineItem(Constants.catalogName, Constants.productId, Constants.variantId, 1);
            buyItem.ShippingMethodId = GetShippingMethodID();
            basket.OrderForms[0].LineItems.Add(buyItem);

            //Add a credit card payment to the basket.
            CreditCardPayment ccPmt = new CreditCardPayment(addressId, GetPaymentMethodID());
            ccPmt.CreditCardIdentifier = ccPmt.PaymentId.ToString();
            ccPmt.ExpirationMonth = 3;
            ccPmt.ExpirationYear = DateTime.Today.Year + 3;
        }

        // At least one credit card payment method must be
        // configured for the site.
        public Guid GetPaymentMethodID()
        {
            Guid creditCardPaymentMethodId = Guid.Empty;
            Boolean ccPmtMethodFound = false;

            // Get all payment methods. 
            DataSet pmtMethods = orderCtx.GetPaymentMethods();
            DataTableReader reader = pmtMethods.CreateDataReader();

            IEnumerator readerEnum = reader.GetEnumerator();
            while (readerEnum.MoveNext() && !ccPmtMethodFound)
            {
                DbDataRecord rec = (DbDataRecord)readerEnum.Current;
                switch (rec.GetInt32(rec.GetOrdinal("PaymentType")))
                {
                    case (int)PaymentMethodTypes.CreditCard:
                        creditCardPaymentMethodId = rec.GetGuid(rec.GetOrdinal("PaymentMethodId"));
                        ccPmtMethodFound = true;
                        break;
                }
            }

            if (ccPmtMethodFound == false)
                throw new ApplicationException("At least one credit card pamyment method must be defined.");
            return creditCardPaymentMethodId;
        }

        // At least one shipping method must be configured for
        // the site.
        public Guid GetShippingMethodID()
        {
            Guid shippingMethodId = Guid.Empty;
            Boolean shipMethodFound = false;

            // Get all shipping methods in the default language.
            DataSet shipMethods = orderCtx.GetShippingMethods();
            DataTableReader reader = shipMethods.CreateDataReader();

            IEnumerator readerEnum = reader.GetEnumerator();
            while (readerEnum.MoveNext() && !shipMethodFound)
            {
                DbDataRecord rec = (DbDataRecord)readerEnum.Current;
                shippingMethodId = rec.GetGuid(rec.GetOrdinal("ShippingMethodId"));
                shipMethodFound = true;
            }

            if (shipMethodFound == false)
                throw new ApplicationException("At least one shipping method must be defined.");
            return shippingMethodId;
        }

        public void CheckPipelineResultAndPrintWarnings(OrderGroup og, PipelineExecutionResult res)
        {
            // Check the error collections.
            if (res == PipelineExecutionResult.Warning)
            {
                Console.WriteLine("The pipeline generated warnings.");
                foreach (OrderForm of in og.OrderForms)
                {
                    Console.WriteLine("_Basket_Errors Collection for OrderForm " + og.OrderForms.IndexOf(of) + ": ");
                    foreach (String basketError in (SimpleList)of["_Basket_Errors"])
                        Console.WriteLine("\t" + basketError);

                    Console.WriteLine("_Purchase_Errors Collection for OrderForm " + og.OrderForms.IndexOf(of) + ": ");
                    foreach (String poError in (SimpleList)of["_Purchase_Errors"])
                        Console.WriteLine("\t" + poError);
                }
                Console.WriteLine();
            }
        }

        public PipelineExecutionResult RunPipeline(OrderGroup og, bool transacted, bool loggingEnabled, String pipelineName, String pipelinePath)
        {
            PipelineBase pipeline;
            PipelineExecutionResult res;
            PipelineInfo pipeInfo = CreatePipelineInfo(pipelineName);

            pipeline = new Microsoft.CommerceServer.Runtime.Pipelines.OrderPipeline(pipelineName, pipelinePath, loggingEnabled, pipelineName + ".log", transacted);
            res = og.RunPipeline(pipeInfo, pipeline);

            CheckPipelineResultAndPrintWarnings(og, res);

            // Release unmanaged resources.
            pipeInfo.Dispose();
            return res;
        }

        public PipelineInfo CreatePipelineInfo(String pipelineName)
        {
            PipelineInfo pipeInfo;

            switch (pipelineName.ToLower())
            {
                case "basket":
                    if (basketPipe == null)
                    {
                        basketPipe = new PipelineInfo(pipelineName);
                        AddDataToPipelineInfo(ref basketPipe);
                    }
                    return basketPipe;
                case "total":
                    if (totalPipe == null)
                    {
                        totalPipe = new PipelineInfo(pipelineName);
                        AddDataToPipelineInfo(ref totalPipe);
                    }
                    return totalPipe;
                case "checkout":
                    if (checkoutPipe == null)
                    {
                        checkoutPipe = new PipelineInfo(pipelineName);
                        AddDataToPipelineInfo(ref checkoutPipe);
                    }
                    return checkoutPipe;
                default:
                    pipeInfo = new PipelineInfo(pipelineName);
                    AddDataToPipelineInfo(ref pipeInfo);
                    return pipeInfo;
            }
        }

        private void AddDataToPipelineInfo(ref PipelineInfo pipeInfo)
        {
            CacheManagerClass cacheManager = null;
            MessageManagerClass msgManager = null;

            // Add the collection of payment processors.
            PipelineBase creditCardPipelineProcessor = new Microsoft.CommerceServer.Runtime.Pipelines.OrderPipeline("CreditCardProcessor", Constants.creditCardPaymentProcessortPcfFilePath, false, Constants.LogFilePath + "\\CreditCard.log", true);

            PipelineCollection pipeCollection = new PipelineCollection();
            pipeCollection.Add("CreditCardProcessor", creditCardPipelineProcessor);

            pipeInfo["pipelines"] = pipeCollection;

            try
            {
                // Create the CacheManager object.
                cacheManager = new CacheManagerClass();

                // Create the MessageManager object.
                msgManager = new MessageManagerClass();

                // Add error message strings for both the
                // current culture and the default culture.
                AddMessagesToMessageManager(msgManager, CultureInfo.CurrentUICulture.ToString(), 1033);
                AddMessagesToMessageManager(msgManager, "en-US", 1033);

                // Populate the dictionary components.
                ConfigureMarketingSystem(pipeInfo, cacheManager);
                ConfigureOrderSystem(pipeInfo, cacheManager);
                ConfigureCatalogSystem(pipeInfo);
                pipeInfo["MessageManager"] = msgManager;
                pipeInfo["CommerceResources"] = resources;
                pipeInfo["cachemanager"] = cacheManager;

                // You must specify the Discounts cache name
                // when running in a non-ASP.NET environment.
                pipeInfo.DiscountsCacheName = "Discounts";
            }
            finally
            {
                // Release unmanaged resources.
                if (cacheManager != null)
                    Marshal.ReleaseComObject(cacheManager);
                if (msgManager != null)
                    Marshal.ReleaseComObject(msgManager);
            }
        }

        public void AddMessagesToMessageManager(MessageManagerClass msgMgr, String language, int locale)
        {
            msgMgr.AddLanguage(language, locale);
            msgMgr.AddMessage("pur_badsku", "One or more items were removed from the basket", language);
            msgMgr.AddMessage("pur_noitems", "No items were found in the basket", language);
            msgMgr.AddMessage("pur_badplacedprice", "Placed price was not correct", language);
            msgMgr.AddMessage("pur_discount_changed", "One or more discounts have changed", language);
            msgMgr.AddMessage("pur_discount_removed", "One or more discounts no longer apply", language);
            msgMgr.AddMessage("pur_badshipping", "Unable to complete order: cannot compute shipping cost", language);
            msgMgr.AddMessage("pur_badhandling", "Unable to complete order: cannot compute handling cost", language);
            msgMgr.AddMessage("pur_badtax", "Unable to complete order: cannot compute tax", language);
            msgMgr.AddMessage("pur_badcc", "The credit-card number you provided is not valid. Please verify your payment information or use a different card", language);
            msgMgr.AddMessage("pur_badpayment", "There was a problem authorizing your credit. Please verify your payment information or use a different card", language);
            msgMgr.AddMessage("pur_badverify", "Changes to the data require your review. Please review and re-submit", language);
            msgMgr.AddMessage("pur_out_of_stock", "At least one item is out of stock", language);
            msgMgr.AddMessage("unknown_shipping_method", "The selected shipping method is not currently available.  Please choose another shipping method", language);
        }

        void ConfigureMarketingSystem(PipelineInfo pipeInfo, CacheManagerClass cacheManager)
        {
            CommerceResource marketingResource = resources["Marketing"];
            string marketingConnStr = marketingResource["connstr_db_marketing"].ToString();
            string cleanedMarketingConnStr;
            CleanSqlClientConnectionString(marketingConnStr, out cleanedMarketingConnStr);

            DictionaryClass marketingCacheDict = new DictionaryClass();
            marketingCacheDict["ConnectionString"] = marketingConnStr;
            marketingCacheDict["DefaultLanguage"] = marketingResource["s_DefaultMarketingSystemLanguage"].ToString();

            ExpressionEvaluator exprEval = null;

            try
            {
                // Create the expression evaluator.
                IExpressionStoreAdapter evaluatorStoreAdapter = new MarketingExpressionStoreAdapter(cleanedMarketingConnStr);
                exprEval = new ExpressionEvaluator();
                exprEval.Connect(evaluatorStoreAdapter);
                pipeInfo["Evaluator"] = exprEval;

                // Set entries in the discounts cache.
                cacheManager.set_RefreshInterval("Discounts", 0);
                cacheManager.set_RetryInterval("Discounts", 60);
                cacheManager.set_CacheObjectProgId("Discounts", "Commerce.Dictionary");
                cacheManager.set_LoaderProgId("Discounts", "Commerce.CSFLoadDiscounts");
                marketingCacheDict["Evaluator"] = exprEval;
                cacheManager.set_LoaderConfig("Discounts", marketingCacheDict);
                cacheManager.set_WriterConfig("Discounts", marketingCacheDict);
                cacheManager.set_WriterProgId("Discounts", "Commerce.CSFWriteEvents");

                // Set entries in the advertising cache.
                cacheManager.set_RefreshInterval("Advertising", 300);
                cacheManager.set_RetryInterval("Advertising", 60);
                cacheManager.set_CacheObjectProgId("Advertising", "Commerce.Dictionary");
                cacheManager.set_LoaderProgId("Advertising", "Commerce.CSFLoadAdvertisements");
                cacheManager.set_WriterConfig("Advertising", marketingCacheDict);
                cacheManager.set_WriterProgId("Advertising", "Commerce.CSFWriteEvents");
            }
            finally
            {
                // Release unmanaged resources.
                if (exprEval != null)
                    Marshal.ReleaseComObject(exprEval);
                if (marketingCacheDict != null)
                Marshal.ReleaseComObject(marketingCacheDict);
            }
        }

        void ConfigureOrderSystem(PipelineInfo pipeInfo, CacheManagerClass cacheManager)
        {
            CommerceResource transactionConfigResource = resources["Transaction Config"];
            string transactionConfigConnStr = transactionConfigResource["connstr_db_TransactionConfig"].ToString();
            string cleanedTxConfigConnStr = null;
            CleanSqlClientConnectionString(transactionConfigConnStr, out cleanedTxConfigConnStr);

            Microsoft.CommerceServer.Runtime.IDictionary shippingMethodCacheDict = new DictionaryClass();
            shippingMethodCacheDict["ConnectionString"] = cleanedTxConfigConnStr;
            shippingMethodCacheDict["TableName"] = "txVirtual_Directory";

            Microsoft.CommerceServer.Runtime.IDictionary paymentMethodCacheDict = new DictionaryClass();
            paymentMethodCacheDict["ConnectionString"] = cleanedTxConfigConnStr;
            paymentMethodCacheDict["TableName"] = "txVirtual_Directory";

           pipeInfo["TransactionConfigConnectionString"] = transactionConfigConnStr;
            try
            {
                // Set entries in the shipping method cache.
               cacheManager.set_RefreshInterval("ShippingManagerCache", 0);
               cacheManager.set_RetryInterval("ShippingManagerCache", 30);
               cacheManager.set_CacheObjectProgId("ShippingManagerCache", "Commerce.Dictionary");
               cacheManager.set_LoaderProgId("ShippingManagerCache", "Commerce.ShippingMethodCache");
               cacheManager.set_LoaderConfig("ShippingManagerCache", shippingMethodCacheDict);
               cacheManager.set_WriterConfig("ShippingManagerCache", shippingMethodCacheDict);

               // Set entries in the payment method cache.
               cacheManager.set_RefreshInterval("PaymentMethodCache", 0);
               cacheManager.set_RetryInterval("PaymentMethodCache", 30);
               cacheManager.set_CacheObjectProgId("PaymentMethodCache", "Commerce.Dictionary");
               cacheManager.set_LoaderProgId("PaymentMethodCache", "Commerce.PaymentMethodCache");
               cacheManager.set_LoaderConfig("PaymentMethodCache", paymentMethodCacheDict);
               cacheManager.set_WriterConfig("PaymentMethodCache", paymentMethodCacheDict);
           }
           finally
           {
               // Release unmanaged resources.
               if (shippingMethodCacheDict != null)
                   Marshal.ReleaseComObject(shippingMethodCacheDict);
           }
       }

        void ConfigureCatalogSystem(PipelineInfo pipeInfo)
        {
            if (!catalogContextCreated)
            {
                CatalogSiteAgent siteAgent = new CatalogSiteAgent();
                siteAgent.SiteName = SiteName;

                // Configure the catalog cache.
                CacheConfiguration catCacheConfiguration = new CacheConfiguration();
                catCacheConfiguration.SchemaCacheTimeout = catCacheConfiguration.ItemInformationCacheTimeout =
                catCacheConfiguration.ItemHierarchyCacheTimeout = catCacheConfiguration.ItemRelationshipsCacheTimeout =
                catCacheConfiguration.ItemAssociationsCacheTimeout = catCacheConfiguration.CatalogCollectionCacheTimeout =
                TimeSpan.FromMinutes(5);

                // Create a CatalogContext object with the
                // cache configurations.
                catalogContext = CatalogContext.Create(siteAgent, catCacheConfiguration);
                catalogContextCreated = true;
            }
            pipeInfo["CatalogContext"] = catalogContext;
        }

        public static bool CleanSqlClientConnectionString(string connectionString, out string cleaned)
         {
             const string PROVIDER_TOKEN = "Provider";
             cleaned = null;
             try
             {
                 OleDbConnectionStringBuilder builder = new OleDbConnectionStringBuilder(connectionString);
                 builder.Remove(PROVIDER_TOKEN);
                 cleaned = builder.ConnectionString;
                 return true;
            }
            catch (ArgumentException)
            {
                // If the connection string is not formatted
                // correctly, ignore the exception and return
                // false.
                return false;
            }
        }
    }

    public class Constants
    {
        // In the following, replace "StarterSite" with the
        // name of your site.
        public const string SiteName = "StarterSite";

        // Replace the paths with the paths to your pipelines
        // and log file, relative to the directory from which
        // you run this program.
        public const string emptyPaymentProcessortPcfFilePath = @"Pipelines\EmptyPaymentProcessor.pcf";
        public const string creditCardPaymentProcessortPcfFilePath = @"Pipelines\CreditCard.pcf";
        public const string LogFilePath = @"Pipelines\Log";

        // Replace "Adventure Works Catalog" with the name
        // of your product catalog, replace "AW078-04" with
        // a product ID, and replace "6" with the variant
        // ID of the product.
        public const string catalogName = "Adventure Works Catalog";
        public const string productId = "AW078-04";
        public const string variantId = "6";
    }
}

The basket.pcf, total.pcf, and checkout.pcf files must be in the \pipelines subdirectory of the directory from which you run this application.

Change the values of the members of the Constants class to represent your configuration.

At least one credit card payment method and one shipping method must be configured for the site.

Compiling the Code

To run this code example, create a console application and add references to the following assemblies:

  • Microsoft.CommerceServer.Catalog.dll

  • Microsoft.CommerceServer.Interop.dll

  • Microsoft.CommerceServer.Runtime.dll

  • Microsoft.CommerceServer.Shared.dll

  • Microsoft.CommerceServer.CrossTierTypes.dll

  • Microsoft.CommerceServer.Orders.CrossTierTypes.dll

See Also

Other Resources

How to Run a Pipeline Outside a Web Application

Working with Orders Runtime Objects Outside a Web Application