
Exposing a BizTalk Orchestration as a Web Service
It is important to note that there is no new underlying infrastructure required to support publishing BizTalk orchestrations as Web services. The BizTalk Web Services Publishing Wizard is a code-generation process that creates a standard C# Web service project. Everything that .NET developers know from creating .NET Web services applies here, from assigning application pools to adding SOAP extensions.
As stated earlier, this white paper does not address WSE 2.0.
How to Expose an Orchestration as a Web Service
There are two ways to launch the BizTalk Web Services Publishing Wizard: from the Start menu entry or from the Tools menu in Visual Studio. If the project you want to publish is the current project in Visual Studio, then launching the wizard from the Tools menu prepopulates the assembly location for you.
After you select an assembly, the wizard looks through it for schemas and orchestrations. Orchestrations containing public ports are listed on the wizard screen. Note that the default type modifier (which controls visibility) for port types is "Internal". You need to change this to "Public" for any ports that you wish to expose as Web services. These ports are published as Web methods, and the messages they send and receive are published as types. Note that you can change the type modifier of an existing port by changing the property in the Port Types node of the Orchestration View.
The SOAP protocol defines an extensibility mechanism whereby you can add SOAP headers to a message. This allows you to send additional information, such as a security token, with a message without modifying the content of the message. In addition, you can specify whether the headers must be understood, meaning that if a message arrives with an unexpected header then it should be treated as a failure and a SOAP fault should be returned. The publishing wizard includes a mechanism for both adding additional headers and specifying whether unexpected headers should be permitted.
When the wizard completes, the final screen gives you a link to the C# project that has been created. Note that you only need to do this generation process if the orchestration ports or schemas change. You can modify the orchestration and redeploy it, and as long as the public interface has not changed you do not need to regenerate the Web service.
The wizard process also generates the appropriate virtual root for your Web service, and the virtual root is configured for the default application pool. A best practice is to create a minimal permission application pool and assign your generated Web services to that pool. If your process is long running and synchronous, you may need to adjust the time-out of the service. For standard ASP.NET Web services you do this by setting the executionTimeout attribute of the httpRuntime element in the Web.config file.
Adding Fault Messages
Earlier in this white paper we saw how to detect and react to faults raised by Web services we consumed. To be a SOAP protocol-compliant service, we need to be able to report any faults back to the client that called us, and to do so in a manner that conforms to the SOAP protocol.
The framework does most of the hard work for us. We simply need to provide a fault message, and it is serialized and returned to the client as a standard SOAP fault. The steps required to implement a SOAP fault are:
-
Create a fault message
-
Add a fault message to the operation of the request/response port that is exposed as a Web service
-
Return the fault message in the event of an error condition
The fault message can be either a complex type or a simple string. Which one you choose depends on the needs of your particular solution. If all you need to do is return a simple message, then create a new message and instead of choosing a schema as the message type, choose System.String. If you need to return more comprehensive information as the fault detail, then specify a message schema. You can map and assign values to your fault message just as you would to any normal message. The content of the message is automatically serialized for you.
An orchestration that can return a SOAP fault when exposed as a Web service might look as shown in the following figure.
Figure 3 Returning a fault message
How to Create an Untyped Web Service
Normally, everything in BizTalk Server 2004 is strongly typed. When you create a receive port in an orchestration, you specify the type of the message being received.
There are, however, cases where you may want to receive multiple types of documents at a single endpoint. Consider the case of a supplier exposing a Web service that its partners can use for multiple purposes: to submit orders, send order change requests, and send cancellations. If these are all different schemas, as likely would be the case, then you need to create multiple endpoints. An alternative approach would be to have a single Web service receive documents, and then use the BizTalk Server publish/subscribe mechanism to route the received documents to the appropriate subscriber based on the type of document received.
The following steps are required to implement this approach:
-
Create a dummy orchestration that receives a message of type System.Xml.XmlDocument. Make sure that the port is Public so that the Web Services Publishing Wizard can expose it.
-
Run the Web Services Publishing Wizard, accepting all the defaults, specifying that you want BizTalk Server to create the ports, and granting it Anonymous access. (After you run the wizard, you no longer need the dummy orchestration. You only created it to have the publishing wizard generate the Web service project.)
-
Create additional orchestrations that receive a message of a known type, such as Order, Cancellation, and Order Change.
In the additional orchestrations created above, set the activating Receive shape's filter to only accept messages of the type you want to receive (for example, BTS.MessageType == "http://GenericXmlDocWS.Invoice#Invoice"). Note that if you do not do this, all documents received by the Web service are processed by all of the orchestrations bound to the Web port.
-
Build and deploy the project.
-
Bind the receive port of the additional orchestrations to the Web port that was created when you published the dummy orchestration.
-
Set the receive location to use the XmlReceive pipeline, so that the incoming document is identified.
To make this work, you need to make a slight code change to the generated Web service. (This is true up to and including BizTalk Server 2004 Service Pack 1, the current version when this paper was written.) Open the project and locate:
string bodyTypeAssemblyQualifiedName = "Microsoft.XLANGs.BaseTypes.Any, Microsoft.XLANGs.BaseTypes, Version=3.0.1.0, Cult" +
"ure=neutral, PublicKeyToken=31bf3856ad364e35";
And change it to:
string bodyTypeAssemblyQualifiedName = string.Empty;
You can start the orchestration. You can submit any XML document to the Web service, but if it is of type Order then it is identified and routed to the appropriate orchestration.