I recently encountered a bit of a “gotcha” when looking at how BizTalk receives WCF messages through its adapters. I expected my orchestration subscription for messages arriving from either the SOAP adapter or WCF adapter to behave similarly, but alas, they do not.
Let’s say I have two schemas. I’m building an RPC-style service that takes in a query message and returns the data entity that it finds. I have a “CustomerQuery_XML.xsd” and “Customer_XML.xsd” schema in BizTalk.
Let’s assume I want to be very SOA/loosely-coupled so I build my web service from my schemas BEFORE I create my implementation logic (e.g. orchestration). To demonstrate the point of the post, I’ll need to create one endpoint with the BizTalk Web Services Publishing Wizard and another with the BizTalk WCF Service Publishing Wizard (using the WCF-BasicHTTP adapter). For both, I take in the “query” message and return the “entity” message through a two-way operation named “GetCustomer.”
Now, let’s add an orchestration to the mix. My orchestration takes in the query message and returns the entity message. More importantly, note that my logical port’s operation name matches the name of the service operation I designated in the service generation wizards.
Why does this matter? Once I bind my orchestration’s logical port to my physical receive location (in this case, pointing to the ASMX service), I get the following subscription inserted into the MessageBox:
Notice that it’s saying that our orchestration will take messages if (a) they come from a particular port, are of a certain type, and not using a SOAP transport, or (b) they come from a particular port and has a specific SOAP method called. This is so that I can add non-SOAP receive locations to this particular port, and still have them arrive at the orchestration. If I picked this up from the FILE adapter, I clearly wouldn’t have a SOAP method that matches the orchestration’s logical port operation name.
For comparison purposes, note that the subscription created by binding the orchestration to the WCF receive location looks identical (except for a different port ID).
Let’s call the SOAP version of the service (and assume it has been bound to the orchestration). If we “stop” the orchestration, we can see that a message is queued up, and that it’s context value match one part of our subscription (receive port with a particular ID, and the SOAP method name matching our subscription). Note that because the InboundTransportType was “SOAP” that the first part of the subscription was followed.
If I rebuild this orchestration with a DIFFERENT port operation name (“GetDeletedCustomer”) and resubmit through the SOAP adapter, I’ll get a subscription error because the inbound message (with the now-mismatched operation in the client’s service proxy) doesn’t match the subscription criteria.
You can see there that we still apply the first port of the subscription (because the inbound transport type is SOAP), and in this case, the new method name doesn’t match the method used to call the service.
Can you guess where I’m going? If I switch back and bind the orchestration to the WCF receive location, and call that service (with now-mismatched operations still in place), everything works fine. Wait, what?? How did that work? If I pause the orchestration, we can see how the context data differs for messages arriving at a WCF endpoint.
As you can see, my InboundTransportType for this receive location is “BasicHttpRLConfig” which means that the subscription is now evaluated against the alternate criteria: port ID, message type and !=SOAP.
So, from what I can see, the actual operation name of the WCF service no longer corresponds to the orchestration logical port’s operation name. It doesn’t matter anymore. The subscription treats WCF messages just like it would FILE or MSMQ messages. I guess from a “coupling” perspective this is good since the orchestration (e.g. business logic) is now even more loosely coupled from the service interface.