SOAP Adapter and BizTalk Web Publishing Wizard

Published on : Aug 17, 2007

Category : BizTalk Server

Saravana

Author

Exposing an Orchestration as Web Service:

This is the safest option you can choose, when you want to expose your business process as an industry standard web service, which can later be consumed by a client (consumer) either using a web service proxy or HTTP post of correctly formatted SOAP message. There is a very good article in MSDN http://msdn2.microsoft.com/en-US/library/ms935219.aspx explaining how you can expose your orchestration as web service. Let’s assume you have exposed your orchestration as web service, bound the inbound logical port to the auto-generated SOAP receive port (created by the wizard) and enlisted-started the Orchestration. Now, when you look at the activation subscription details for the Orchestration it will look something similar to the one shown below:   SNIPPET #1
http://schemas.microsoft.com/BizTalk/2003/system-properties.ReceivePortID == {73684F88-8D5C-4659-9E8F-F1B5E6E9A780} And http://schemas.microsoft.com/BizTalk/2003/system-properties.MessageType == http://www.digitaldeposit.net/samples/schema/1.0#personRequest And http://schemas.microsoft.com/BizTalk/2003/system-properties.InboundTransportType != SOAP Or http://schemas.microsoft.com/BizTalk/2003/system-properties.ReceivePortID == {73684F88-8D5C-4659-9E8F-F1B5E6E9A780} And http://schemas.microsoft.com/BizTalk/2003/soap-properties.MethodName == GetPersonDetail
  When you are receiving the messages via the auto-generated SOAP receive port the properties MethodName and ReceivePortID will get promoted by the SOAP adapter and the orchestration will get the message due to second subscription condition. (MethodName will equate to the Operation name you defined inside the logical port within your Orchestration) If you inspect the first condition carefully, you’ll see if MessageType property is present then the receive adapter should NOT be SOAP. Also, the auto-generated SOAP ReceiveLocation uses PassThru pipeline, which results in MessageType property not being promoted. This design introduces two potential problems (LISTING #1)
    1. Configuring MAP(S) on the auto-generated SOAP receive port will be ignored.
    2. Properties (distinguished and promoted) defined in the schema wont get into the context.

Maps will be ignored on the auto-generated SOAP Receive Port:

Usage of PassThru pipeline inside the auto-generated SOAP ReceiveLocation is bit contrary when you are using Orchestrations and dealing with XML messages. Majority of the time Orchestration subscriptions will be based on MessageType you specified on the Activation receive shape and you’ll be using XmlReceive pipeline on your ReceiveLocation, so that MessageType and other property promotions (both distinguished and promoted properties defined in the schema) gets into the context. Since the MessageType property is NOT promoted anywhere in the ReceivePort (mainly due to the usage of PassThru pipeline), any MAP you configure on the ReceivePort will be ignored. Due to the configuration of PassThru pipeline by default, any properties (both distinguished and promoted) defined in your schema won’t get into to the context, which creates potential problem if you want to use content based routing. We can fix these problems easily, by modifying the auto-generated SOAP ReceiveLocation to use XmlReceive pipeline instead of PassThru. As I mentioned in the beginning “Exposing orchestration as web-service” is the safest option, it doesn’t introduce too much head aches. The problem really starts when you just want to expose your schemas as web services as explained in next topic.

Exposing schemas as web services:

The MSDN article http://msdn2.microsoft.com/en-US/library/ms935219.aspx got clear explanation of exposing schemas as web services. After exposing your schemas as web-services using “BizTalk Web Publishing” wizard, you can create an Orchestration to consume the messages published by the auto-generated SOAP ReceivePort. The important thing to note here is the name of the “Operation” you define inside the logical port, make sure it matches the WebMethod name you have specified while generating the web-service. As shown in the below figure: biztalk web service When you bind the logical orchestration port to physical auto-generated SOAP ReceivePort and start (enlist) the orchestration, the subscription for the orchestration will look identical to the one shown in SNIPPET #1 (earlier). We’ll hit the same problems (explained in detail earlier) outlined under “Exposing an Orchestration as web service”
  1. Map won’t get applied
  2. Properties (distinguished and promoted) won’t get into context
Due to the fact, the auto-generated SOAP ReceiveLocation uses PassThru pipeline by default. If you modify the auto-generated SOAP ReceiveLocation to use XmlReceive pipeline instead of PassThru (hoping its going to fix all the problems, as we did with “Exposing an Orchestration as web service”) the run-time will generate the following exception when it receives the message:
There was a failure executing the receive pipeline: “Microsoft.BizTalk.DefaultPipelines.XMLReceive, Microsoft.BizTalk.DefaultPipelines, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35” Source: “XML disassembler” Receive Port: “WebPort_SK.ws.viaSchemas.1_0/WebService1” URI: “/SK.ws.viaSchemas.1_0/WebService1.asmx” Reason: The type SK.Schemas.Person_1_0 is not a valid part type for a message. This invalid type may be from a property schema.
The exception is mainly raised because SOAP adapter puts the wrong DocumentSpecName property in the message context and hands over the message to the pipeline. PassThru pipeline (DEFAULT Configuration on auto-generated SOAP ReceiveLocation) doesn’t do any processing, so whatever value present in the property DocumentSpecName is ignored. On the other hand if you configure XmlReceive pipeline which uses XmlDisassembler, it will utilizes the “DocumentSpecName” property to resolve the schema.

Behavior of XmlDissambler inside the XmlReceive pipeline:

Having the DocumentSpecName property in the context, will force XmlDissambler pipeline component to use it, to locate your schema. If DocumentSpecName is NOT present then XmlDissambler pipeline component will go through dynamic schema resolution mechanisms to get the correct schema. Since DocumentSpecName is present with wrong value, XmlDissambler throws the exception and it clearly states “This invalid type may be from a property schema”. There are few ways you can get away from this problem

Solution #1: Use PassThru pipeline and Orchestration (DEFAULT config):

If you don’t have any inbound maps to be applied on the port level and you are not dependant on promoted properties (distinguished and promoted) defined in the schema outside the orchestration, then you can use PassThru pipeline (configured by default by auto-generated SOAP receive location). The Orchestration gets the message by other subscription conditions (ex: MethodName) without the need for MessageType.
  1. You can get away from the MAP problem by applying it inside your orchestration, and
  2. You automatically get away from property promotion problem. Because when the orchestration receives a message the IBaseMessage (from adapter/pipeline) is converted into a XLANG message, which results in the process of new message construction (since messages are immutable in BizTalk server). During this step all the distinguished and promoted properties gets into the context. [This is my own prediction of how distinguished fields and promoted properties gets into the context automatically within Orchestration even though we used PassThru pipeline, I couldn’t find clear documentation explaining it] and available within the Orchestration.

Solution #2: Modify the generated .asmx.cs code. Passing null instead of bodyTypeAssemblyQualifiedName:

By passing the value “null” instead of bodyTypeAssemblyQualifiedName both the problems defined in Listing #1 can be solved //Original Code
string bodyTypeAssemblyQualifiedName = “SK.Schemas.Person_2_0, SK.Schemas, Version=1.0.0.0, Culture=neutral, PublicKeyTok” + “en=c2b0cafd9314ef3e”; // BizTalk invocation object[] invokeResults = this.Invoke(“GetPersonDetail”, invokeParams, inParamInfos, outParamInfos, 0, bodyTypeAssemblyQualifiedName, inHeaders, inoutHeaders, out inoutHeaderResponses, out outHeaderResponses, null, null, null, out unknownHeaderResponses, false, false);
//Modified Code
// BizTalk invocation object[] invokeResults = this.Invoke(“GetPersonDetail”, invokeParams, inParamInfos, outParamInfos, 0, null, inHeaders, inoutHeaders, out inoutHeaderResponses, out outHeaderResponses, null, null, null, out unknownHeaderResponses, false, false);
If the value null is passed instead of bodyTypeAssemblyQualifiedName, SOAP adapter won’t add the DocumentSpecName property to the context. Now, when we configure our auto-generated SOAP ReceiveLocation to use XmlReceive pipeline, the XmlDisassembler component inside XmlReceive will go through the process of automatic dynamic schema resolution mechanism, pick up the correct schema and promotes all the required properties (distinguished and promoted) defined in the schema and it also promotes the MessageType property.

Solution #3: Modify the generated .asmx.cs code. Change bodyTypeAssemblyQualifiedName property to include the schema root node.

We are going to follow a similar approach here, but instead of passing null”for bodyTypeAssemblyQualifiedName, we are actually going to pass the correct value. //Original Code
string bodyTypeAssemblyQualifiedName = “SK.Schemas.Person_2_0, SK.Schemas, Version=1.0.0.0, Culture=neutral, PublicKeyTok” + “en=c2b0cafd9314ef3e”;
//Modified Code
string bodyTypeAssemblyQualifiedName = “SK.Schemas.Person_2_0+personRequest, SK.Schemas, Version=1.0.0.0, Culture=neutral, PublicKeyTok” + “en=c2b0cafd9314ef3e”;
The only difference is we are appending the schema root element name to the schema Type Name. You can see the correct DocumentSpecName name by
  1. Add a Receive Pipeline to your project (or to a dummy project),
  2. Drag-Drop a XmlDisassembler component
  3. Select XmlDisassembler and in the properties window, click on button next to the “Document Schemas” property. You’ll see “Schema collection property editor” window as shown in the below figure, which clearly shows the expected “DocumentSpecName” name.
schema collection property editor When you expose your Orchestration as web service the auto generated code will look similar to our modified code. NOTE: You need to be careful with Solution #2 and #3, because regenerating the web-service code will result in losing the manual changes you performed. You can download the ZIP file containing all the sample projects I used for this research.