Modifying Messages with the WCF Adapters
|To download a copy of this document, go to http://go.microsoft.com/fwlink/?LinkId=129534.|
Within the Windows Communication Foundation (WCF) adapters is the ability to modify both incoming BizTalk® messages and outgoing WCF messages. For inbound WCF messages, you can specify what part of the incoming WCF message to use as the source of the BizTalk message body by using an XPath expression. Once an outbound BizTalk message is sent to a send port configured to use a WCF adapter, the message is converted to a WCF message. You can modify the content of the outbound WCF message body by using an XML template.
Both of these capabilities are available through the Messages tab in the Transport Properties dialog box from within the BizTalk Server Administration console. Based upon the type of a send port (one-way or solicit-response) or a receive location (one-way or request-response), the top-to-bottom order and availability of the Inbound BizTalk message body and Outbound WCF message body sections will be affected. For instance, for a one-way receive location, only the Inbound BizTalk message body section is enabled (the Outbound WCF message body section is disabled).
Outgoing WCF Message Body
There are two options for the Outbound WCF message body section of the Messages tab in the Transport Properties dialog box for the send port configured to use a WCF adapter:
- Body – BizTalk request message body
- Template – body is specified by a template
The “Body” option is the default choice. It takes the body of the incoming BizTalk message as the body of the outgoing SOAP envelope (WCF message).
The “Template” option is a more flexible choice and can be used to add wrapper elements around the body of an outgoing WCF message.
Suppose we have an AddEmployee.xml file to be sent to the IAddEmployee:AddEmployee method through the send port using a WCF adapter to add an employee. The corresponding SOAP action in the send port Transport Properties dialog box of a WCF send adapter would be http://test.com/employees/IAddEmployee/AddEmployee. We then configure a File receive location to accept the AddEmployee.xml file and input it into BizTalk Server. Due to this send port action, and the AddEmployee xmlns=”http://test.com/employees” element, the WCF send adapter will call the AddEmployee method and send it the AddEmployee.xml file to be processed.
<AddEmployee xmlns=”http://test.com/employees”> <employee> <firstname>David</firstname> <lastname>Johnson</lastname> <empid>33345</empid> </employee> </AddEmployee>
Now suppose that instead of having an AddEmployee.xml file, we have an Employee.xml file that is the same as the AddEmployee file but does not have the <AddEmployee xmlns=”http://test.com/employees”> element.
<employee> <firstname>David</firstname> <lastname>Johnson</lastname> <empid>33345</empid> </employee>
We would like to reshape this Employee record and add the wrapper element <AddEmployee xmlns=”http://test.com/employees”> </AddEmployee> to be able to create an file for the WCF send adapter that looks like the AddEmployee.xml file. There are a few ways to do this. You could add a map to the send port, use a Construct Message shape in an orchestration, or use the Messages tab in the Transport Properties dialog box for a WCF adapter and use a message template. We will discuss the last choice.
Copy the wrapper <AddEmployee xmlns=”http://test.com/employees”> </AddEmployee> to the clipboard. In the Transport Properties dialog box for the WCF send adapter, on the Messages tab, select Template - content specified by template. In the XML box, the bts-msg-body is a token that represents the body of the BizTalk message. At run time it is replaced with the encoded BizTalk message body. This encoding occurs based upon the encoding attribute in the XML template. For instance, in the line below, XML encoding would be used for just the body element. Additionally, base64, hex, or string could have also been chosen.
<bts-msg-body xmlns="http://www.microsoft.com/schemas/bts2007" encoding="xml"/>
To wrap the Employee.xml record with the AddEmployee wrapper, simply copy the starting wrapper text before the body text and the ending part of the element after the body text.
< AddEmployee xmlns=”http://test.com/employees”> <bts-msg-body xmlns="http://www.microsoft.com/schemas/bts2007" encoding="xml"/> </AddEmployee>
Now if you drop a copy of Employee.xml into the File receive location, the WCF adapter on the subscribed send port will add the AddEmployee wrapper to it. When the message comes out of the send port, based upon the AddEmployee wrapper, it will call the AddEmployee method of the service with the received XML file.
Incoming BizTalk Message Body
On the incoming side, there are three options to specify how the BizTalk message body is extracted from the incoming SOAP message. These are found in the Inbound BizTalk message body section of the Messages tab in the Transport Properties for a WCF adapter.
- Envelope – uses the entire soap:Envelope contents as the message body
- Body – uses the entire soap:body contents as the message body
- Path – content is specified by the body path
Envelope and Body elements don’t need any further explanation, but it is useful to discuss the Path option and the expression used within that field. The body path expression used for the Path option is forward-only XPath syntax. For a description of XPath syntax, refer to http://go.microsoft.com/fwlink/?LinkId=121114. You also specify the type of the element being targeted – string, XML, base64, or hex.
One way to return all possible values that match the service response for an XPath expression is to use the union command and the local-name function. For instance:
The first element in the XPath expression could be the message contract generated by WCF, which has the same name as the operation contract (“PlaceOrder”). The element following this (“PurchaseOrder”) could be the name of the parameter inside the message contract. This directs the WCF adapter to parse through the PlaceOrder message contract and pass the PurchaseOrder element to BizTalk Server as the message body.
Example: Suppose we receive the following incoming WCF SOAP message from a WCF client using one of the WCF adapters:
<s:Envelope xmlns:a=\"http://www.w3.org/2005/08/addressing\" xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\"> <s:Header> <a:Action s:mustUnderstand=\"1\">http://tempuri.org/IReceiveMessage/ReceiveMessage </a:Action> </s:Header> <s:Body> <DisplayWCFMessage xmlns=\"http://Microsoft.ServiceModel.Samples.MessageOptionsService\"> <strUserID>'UserID445588'</strUserID> <strMessage>'Message for this user'</strMessage> <strPhoneNum>'888-888-8888'</strPhoneNum> </DisplayWCFMessage> </s:Body> </s:Envelope>
We can enter this XPath expression in the Path field, using the XML encoding option.
/*[local-name()="DisplayWCFMessage" and namespace-uri()='http://Microsoft.ServiceModel.Samples.MessageOptionsService']/*[local-name()='strUserID']
The incoming WCF SOAP message is transformed by the adapter into the following inbound BizTalk message body:
<s:Body> <strUserID xmlns="http://Microsoft.ServiceModel.Samples.MessageOptionsService">'UserID445588'</strUserID> </s:Body>
Using the options on the Messages tab of the Transport Properties dialog box allows massaging of incoming WCF and outgoing BizTalk messages. By using an XML template or a custom XPath expression, you can modify the body of the message and add custom processing to a receive location or send port.