In the newly released BizTalk Server 2013 we finally got an adapter for the WCF WebHttpBinding enabling us to expose and consume REST endpoints. BizTalk has for a long time had strong support for SOAP services (SOAP adapter and later WCF-* adapters). One major difference between SOAP and REST is that a SOAP message will always contain a message body and a message header making it easy to map the SOAP body to a typed message deployed in BizTalk. A REST message does not necessarily contain a body, in fact a GET request will only consist of a URI and HTTP headers.
So how do we translate this type of request to the strongly typed world of BizTalk?
If we start by looking at an example where we want to be able to query a database for product prices via BizTalk.
If we were to expose a SOAP service to the client, the solution could look something like this (irrelevant implementation details excluded):
The client sends a SOAP message to BizTalk. The adapter extracts the message from the body. The message is passed on to the receive pipeline where the message type is determined. Since the message type is known we can perform transformations on it on the send port.
That is old news, bring on the new stuff.
When the client wants to GET something from the server in a RESTful way it uses HTTP GET verb on a resource.
GET http://localhost/ProductService/Service1.svc/Products/680 will instruct the server to get product 680. Note that there isn’t any message body, just a verb and a resource identified by a URI.
So how can we consume this in BizTalk?
The WCF-WebHttp adapter does some of the heavy lifting for us and extracts the parameters from the URI and writes them to the message context.
The XML in BtsHttpUrlMapping tells BizTalk what URIs and what verbs on that URI we want to listen on. In the URI for the first operation we have defined a placeholder for a variable inside curly braces. That is what enables us to ask for a specific product:
If we click the Edit button in the Variable Mapping section we can map this placeholder variable to a property defined in a property schema.
So we need to define a property schema for our ProductId property and promote it from our request schema.
If we change our WCF-WSHttp port to use the WCF-WebHttp adapter with the above configuration and update our client to send REST request the client would receive an error and there will be a suspended message in BizTalk saying “No Disassemble stage components can recognize the data.”
As expected the message body is empty and our ProductId is written to the context. The empty message body causes the XMLDisassembler to fail.
What we need is a custom disassembler pipeline component to create a strongly typed message from the context properties written by the adapter.
The interesting part here is of course the custom disassembler component. It has one parameter, DocumentTypeName. This property is where we define the schema of the message it should create.
If we run the previous request through this component we now get a message body: