Why does the Adapter say ‘Action is not understood’ even though I am using the binding file generated by the ‘Consume Adapter Service’ wizard?

Believe me, the adapter is telling the truth! It really doesn’t understand the action it got! To understand what’s going on, read on…

When you use the ‘Consume Adapter Service’ wizard to generate LOB schemas in a BizTalk project, you also get a binding file which you can import (using the BizTalk Administration Console) to create the corresponding physical WCF-Custom port (Send or Receive Port, based on whether the contract was Outbound or Inbound respectively) when deploying your BizTalk Application. While this does save you the pain of creating and configuring the port manually, there is a ‘not-so-obvious’ caveat which you need to be aware of. (This applies only to send ports i.e. Outbound Contracts)

The WCF-Custom Adapter allows the SOAP Action to be specified in the following two ways on the static send ports:-

  1. As a single line of text – the port is used for a single intended operation (say ‘ABC Action’).

  2. As an xml, mapping each of a set of ‘Operations’ to the corresponding SOAP Action. This xml looks something like this:- (namespaces omitted for clarity)

    <BtsActionMapping>
                <Operation Name =”ABC” Action = “ABC Action” \>
                <Operation Name = “XYZ” Action = “XYZ Action” \>
    </BtsActionMapping>

The binding file created by the ‘Consume Adapter Service’ wizard chooses the second method to specify the action, even if you generate schemas for a single operation.

Now the question is, when a message comes to a port using such a mapping, how does it know what the intended operation was? Or more specifically, how does it know which action to use for which incoming message?

To make this decision, the WCF-Custom adapter compares the message’s BTS.Operation context property with the list of operations in the map (attribute ‘Name’). If a match is found, the corresponding action is used.

However, if the WCF-Custom adapter fails to resolve the operation name from the map, it assumes that the entire thing specified is a single line action (as in 1 above) and sends the whole string to the target adapter binding.

The most common scenario this could happen is when you create an orchestration and forget to change the operation names on the logical ports to appropriate names . By default, when you create a logial port in an orchestration, it’d be created with a single operation called ‘Operation_1’ . The next operation you add (either on the same port or while creating another port) would be called ‘Operation_2’ and so on. You need to modify these default names to the appropriate names as the BTS.Operation context property derives it’s value from the operation name on the logical orchestration port which published the message to the message box. (That also means if you are not using orchestration and still want to use the Action-Mapping feature, you’ll probably need to write a custom pipeline component to populate this context property).

So if you are seeing the error mentioned in the title, what is possibly happening is this:-

Your FOO Adapter supports two operations with the corresponding actions being ‘ABC Action’ and ‘XYZ Action’. You generate the schemas and the binding file, create an orchestration (but forget to change the default operation names), tie the message types, deploy the project and import the binding file.

At runtime when you send a message, because you did not change the operation name on the logical port, the BTS.Operation property is set to ‘Operation_1’. The WCF-Custom adapter tries to look up this name in the map you specified on the send port (by importing the binding file). Since it does not find any operation by the name ‘Operation_1’, the WCF-Custom adapter believes that whatever you specified on the port is a single line action and passes the same to the FOO adapter.

So, instead of getting “ABC Action” or “XYZ Action”, which it understands, the FOO adapter gets “<BtsActionMapping><Operation Name =”ABC” Action = “ABC Action” \><Operation Name = “XYZ” Action = “XYZ Action” \></BtsActionMapping>”.

Clearly, it doesn’t understand that action!

Ok, so what do I do to fix this?

 

In the above example, you should change the operation names on the logical ports in the orchestration to ‘ABC’ and ‘XYZ’ instead of the default ‘Operation_1’, ‘Operation_2’ etc. (Of course, you can also do it the other way round – change the mapping on the port to use names in the orchestration or, if there is just one action to use, specify the action directly on the port instead of using the action map.)
Basically, you need to make sure that the WCF-Adapter is able to resolve the operation name on the message to use the correct action, as explained above.