The Microsoft® Market sample site illustrates the use of a Commerce Interchange Pipeline (CIP) in an extended, practical example. Microsoft Market is a business-to-business site demonstrating internal corporate purchasing, based on Microsoft's own internal corporate purchasing site. The application enables employees to order office supplies from their desktop using a Web browser. The result of the shopping process is the generation and transmission of a purchase order to the vendor that supplies the goods.
This section illustrates how the Market site uses a Commerce Interchange Pipeline (CIP) transmit pipeline to transmit a purchase order by HTTP.
In most Commerce Server sites, the final purchase is processed by an OPP running a purchase configuration. Microsoft® Market follows the same model. In this case, the purchase configuration file is called SubmitViaInterchange.pcf, which is based on the Corporate Purchasing Submit Pipeline template.
This pipeline configuration checks whether the order total requires manager approval and sends mail to the approving manager. If the order is pre-approved, it inserts the requisition in the database and executes a Commerce Interchange Pipeline (CIP) that includes stages for digitally signing and encrypting the requisition and sending it to the vendor using an HTTP post.
As the following figure illustrates, three pipelines are involved. Within the OPP, a CIP is created to perform the business-to-business transaction.
The outer pipeline executes the Scriptor component that runs TxHTTP.vbs. TxHTTP.vbs, in turn, creates and executes the Commerce Interchange Pipeline. When the Interchange pipeline completes execution, control returns to the outer pipeline. The last component of that pipeline is then executed.
Meanwhile, the purchase order is received on the vendor's system using HTTP post. (In the sample site, for simplicity of the demonstration, GetOrder.asp is run on the same computer that is hosting Microsoft Market.)
The outer pipeline, the OPP, is created as an MtsTxPipeline object so that all operations within that pipeline are supported as a single transaction by Microsoft® Transaction Server (MTS). The inner pipeline, the Interchange, is created as an MtsPipeline object so that its components run within the same transaction created by the outer pipeline. (If the inner pipeline were created as MtsTxPipeline object, a failure of any process within it would only roll back the processes in the inner pipeline, not in the outer pipeline.)
The Transmit pipeline is created and executed by a Scriptor component running the script TxHTTP.vbs.
The function defined in this script takes four arguments, but only the orderform
argument is used in the function. This argument represents the requisition that is being transmitted to the vendor.
Assuming the requisition is pre-approved, the function begins by creating a non-transacted pipeline (mscsMtsPipeline
) and loading the InterchangeTransmit.pcf pipeline configuration file. This is the Commerce Interchange Pipeline (CIP).
Next, the function creates a Transport Dictionary to be passed as an argument to the CIP. The Transport Dictionary contains a name/value pair that contains the business data object being sent (in this case, the requisition). In this function, the following phrase adds a value called Object
to the Transport Dictionary, and sets this value as the requisition passed into this function:
Set TransportDictionary.object = orderform
Note Although the Microsoft Market sample uses the name working_data
to represent the business data object, the preferred standard convention is to name this value Object
. Also, the name object
, and not working_data
, should be specified as the Object Source Key in the MapToXML component that appears in Microsoft Market's Transmit pipeline. This documentation uses the correct convention.
The object
property is used by the first component in the Interchange Transmit pipeline, MapToXML, which reads the object¸ maps the object to serialized binary form, and writes the result back into the working_data
property.
Finally, the function executes the Interchange pipeline's Execute method, passing the transport dictionary and the PipeContext dictionary as arguments.
Function mscsexecute(config, orderform, context, flags)
mscsexecute = 1
if (not orderform.needapproval) then
Dim mscsMtsTxPipeline
Set mscsMtsTxPipeline = CreateObject("Commerce.MtsTxPipeline")
Dim pathPipeConfig
REM -- INTTRANSMIT is used , in global.asa to map the interchange pipeline to the file InterchangeTransmit.PCF.
pathPipeConfig = context.pipemap("INTTRANSMIT")
mscsMtsTxPipeline.loadpipe (pathPipeConfig)
REM -- Comment here to turn logging off
if (context.logpipeline) then
call mscsMtsTxPipeline.setlogfile(context.approot + "\data\InterchangeTransmitPipe.log")
end if
REM -- create the outer dictionary which the Interchange pipeline components will use as their black-board
Dim TransportDictionary
Set TransportDictionary = CreateObject("Commerce.Dictionary")
Set TransportDictionary.object = orderform
REM -- for the auditlog
TransportDictionary("requisitionid") = orderform.requisitionid
TransportDictionary("insertby") = orderform.insertby
TransportDictionary("reqemailalias") = orderform.reqemailalias
Dim ierrorlevel
REM -- kick off the Interchange pipeline
On error resume next
ierrorlevel = mscsMtsTxPipeline.execute(1, TransportDictionary,Context, 0)
REM -- return any errors from the Interchange pipeline execution
if (0 <> Err) then
orderform.[_purchase_errors].Add("#:" & Err.Number & "," & Err.Description)
mscsexecute = 3
End if
on error goto 0
if (1 < iErrorlevel) and (0 = orderform.[_purchase_errors].Count) then
orderform.[_purchase_errors].Add(replace(mscsMessageManager.GetMessage("cip_transmit_error"),"%1",ierrorlevel))
end if
end if
End Function
Microsoft Market's InterchangeTransmit.pcf pipeline configuration is an example of a Commerce Interchange Transmit pipeline.
The pipeline begins with the requisition object passed to it in the transport dictionary, and during the course of running the pipeline, various components write new values into the transport dictionary.
The Map stage in this pipeline contains a MapToXML component, which reads the data in the business data object (using the object's IPersistXML or IPersistStreamInit implementation), and writes the data as an XML-enclosed binary stream or as pure XML data to the working
_data
name/value pair.
The Digitally Sign and Encrypt stages in this pipeline are empty so that the Market sample site will work even on servers that do not have installed the certificates that these components require.
The Transport stage contains the SendHTTP component, which send the business data object as an argument to an HTTP request.
When the pipeline has completed execution, the transport dictionary is automatically destroyed (although the original order form object remains).
Getorder.asp is the page that is run on the vendor system to receive the requisition posted by HTTP.
The TxHTTP.vbs script previously described creates a transport dictionary to pass the order form to the InterchangeTransmit pipeline. This Dictionary initially contains the order form object, and is used by other components in the CIP Transmit pipeline to write intermediate values.
Similarly, the script in GetOrder.asp creates a transport dictionary, which it passes as an argument to the pipeline. This script uses the request.form method to retrieve the information posted to the page using HTTP, and creates a name/value pair in the transport dictionary (called Text
) to contain this text.
Next, this script creates a transacted pipeline (mscsMtsTxPipeline
) and loads the Receive.pcf pipeline configuration.
<!-- #include file="include/shop.asp"-->
<!-- #include file="include/utility.asp"-->
<html>
<head>
<!-- #include file="include/standardhead.asp"-->
</head>
<body>
<%
REM -- receive the orderform that is posted thru HTTP.
Dim TransportDictionary
set TransportDictionary = server.createobject("commerce.dictionary")
TransportDictionary.working_data = request.form
Dim mscsMtsTxPipeline
set mscsMtsTxPipeline = server.createobject("commerce.MtsTxPipeline")
REM -- Get the name of the Commerce Interchange Pipeline using INTRECEIVE to key into the pipemap dictionary.
REM -- INTRECEIVE maps to /market/config/InterchangeReceive.pcf in global.asa
call mscsMtsTxPipeline.loadpipe(pipemap("INTRECEIVE"))
if (logpipeline) then
call mscsMtsTxPipeline.setlogfile(Request.ServerVariables("APPL_PHYSICAL_PATH") + "/data/InterchangeReceivePipe.log")
end if
Dim ierrorlevel,context
set Context = server.createobject("commerce.dictionary")
Context.DefaultConnectionString = MSCSSite.DefaultConnectionString
Context.SiteName = MSCSSite.DisplayName
set Context.CIP_receiveerrors = Server.CreateObject("Commerce.SimpleList")
set Context.CIP_receiveDBerrors = Server.CreateObject("Commerce.Dictionary")
on error resume next
ierrorlevel = mscsMtsTxPipeline.execute(1, TransportDictionary, Context, 0)
REM -- Errors are logged to the W3SVC error logs. In order for the specified string to be recorded in the log file,
REM -- select the URI Query option of the Extended Logging Properties sheet for the site.
Dim ErrNumber, ErrText, iError
ErrNumber = Err.Number REM -- store the errors if any, and display if no errors raised by other pipeline components.
ErrText = Err.description
on error goto 0
for each iError in Context.CIP_receiveDBerrors
Response.AppendToLog(Context.CIP_receiveDBerrors(iError))
next
for iError = 0 to Context.CIP_receiveerrors.Count - 1
Response.AppendToLog(Context.CIP_receiveerrors(iError))
next
if (0 = Context.CIP_receiveDBerrors.count) and (0 = Context.CIP_receiveerrors.count) and (0 <> ErrNumber) then
Response.AppendToLog("#:" & ErrNumber & "," & ErrText)
end if
if (1 < iErrorlevel) then
Response.AppendToLog(E_PIPELINE_ERRORLEVEL)
end if
%>
</body>
</html>
Microsoft Market's InterchangeReceive.pcf pipeline configuration is an example of a Commerce Interchange Receive pipeline.
Essentially, this pipeline performs the opposite actions of the Commerce Interchange Transmit pipeline, and in reverse order. Specifically, the pipeline contains the following stages and components.
The Decrypt and Verify Digital Signature stages are empty, because the object was not encrypted or digitally signed when transmitted.
In the Map stage, the MapFromXML component converts the binary stream to a Transport Dictionary, the OBJECT
name/value pair of which references the business data object (an OrderForm).
In the Application Integration stage, a Scriptor component (VendorPOAccept.vbs) writes the values from the OrderForm object to the vendor's database.