Now, as promised, let's take a deeper look at the SOAP actions and how the WCF-Custom adapter deals with them. The idea behind the SOAP actions is quite simple. Essentially, the SOAP action is just a tag attached to the incoming WCF messages telling the adapter what operation it has to perform.
To illustrate the concept by a concrete example, let's refer to the source code provided with the Echo adapter. The point of our interest is the Execute method of the Microsoft.ServiceModel.Channels.Common.IOutboundHandler
interface. This interface is one of the core interfaces that all ASDK-based adapters supporting outbound operations must implement. The Execute is called by the ASDK runtime to perform an outbound operation. Here is the implementation:
The code is self-explanatory and as you can clearly see, is action-centric. If the action coming with the SOAP header is recognized, the adapter performs the requested operation, if not, then the adapter responds with "Invalid Operation" exception. Since the Echo adapter exposes only one operation, using actions may seem unnecessary, but imagine the situation when an adapter exposes multiple operations? In such cases, using the SOAP actions is quite a logical way to help the adapter to decide what operation to perform.
There are two different ways to associate a BizTalk message with the appropriate SOAP action (or to attach the appropriate processing tag as you wish). One is to configure physical send ports using so called Action Mappings. The other is to set the actions dynamically at runtime.
You will use the Action Mappings in the majority of cases—this is the easiest way to configure physical ports since the Consume Adapter Service Wizard does most of the job. For each operation that you selected at the design time, the Consume Adapter Service Wizard will generate a corresponding Operation entry inside the BtsActionMapping wrapper and place the mapping into the physical port binding file it will generate. In the general form, the action mapping looks as follows:
To process the actions mappings and attach the SOAP actions tags to incoming messages, the WCF-Custom adapter uses the following algorithm:
When the outbound message leaves an orchestration, the orchestration instance sets the BTS.Operation context property with the logical port operation name. Once the subscription mechanism pulls the message from the message box and hands it over to the physical port for processing, the WCF-Custom adapter tries to look up the actions map for the Operation with the Name matching the BTS.Operation property. If a match is found, then the adapter attaches the corresponding Action value to the message and sends it to the custom binding for execution. If a match was not found, then the WCF-Custom adapter treats the entire BtsActionMapping as one big action, so the custom binding will get the following action:<BtsActionMapping><Operation Name="Operation 1" Action =......</BtsActionMapping>
with quite a predictable consequence—"Invalid action" exception. So, the rule is clear: for each orchestration outbound operation, there must be an Operation entry in the corresponding physical port action mappings with the Name attribute value matching the orchestration operation name.
It is important to note that for the content-based routing scenarios, where you don't use orchestrations and rely solely on the functionality provided by the messaging engine, you don't have to write a custom pipeline component to set the BTS.Operation context property. Luckily, the WCF-custom adapter supports an alternative single action format.
Essentially, this means that all messages arriving to the send port configured for the single action processing will be tagged with the same action regardless of the BTS.Operation context property. Since the Echo adapter supports only one operation, the single action approach is an alternative solution perfectly applicable to our sample application.
In the situations where you want to postpone the decision on what operation has to be performed until the runtime, you can use the WCF.Action context property. All you need to do is to add an Expression shape to your orchestration and configure the shape to execute the code similar to the presented below:
YourOutboundMessage(WCF.Action)="DesiredAction"
As you can see, the WCF-Custom adapter offers enough flexibility to address virtually any situation you may encounter. Once you understand the concept and available options, all it takes is accuracy and no longer than a couple of minutes to configure send ports.