In my previous post, I looked at how the BizTalk Server 2013 beta supports the receipt of messages through REST endpoints. In this post, I’ll show off a couple of scenarios for sending BizTalk messages to REST service endpoints. Even though the BizTalk adapter is based on the WCF REST binding, all my demonstrations are with non-WCF services (just to prove everything works the same).
Scenario #1 Consuming “GET” Service From an Orchestration
In this first case, I planned on invoking a “GET” operation and processing the response in an orchestration. Specifically, I wanted to receive an invoice in one currency, and use a RESTful currency conversation service to flip the currency to US dollars. There are two key quirks to this adapter that you should be aware of:
- Consumed REST services cannot have an “&” symbol in the URL. This meant that I had to find a currency conversion service that did NOT use ampersands. You’d think that this would be easy, but many services use a syntax like “/currency?from=AUD&to=USD”, and the adapter doesn’t like that one bit. While “?” seems acceptable, ampersands most definitely are not.
- The adapter throws an error on GET. Neither GET nor DELETE requests expect a message payload (as they are entirely URL driven), and the adapter throws an error if you send a GET request to an endpoint. This is a problem because you can’t natively send an empty message to an adapter endpoint. Below, I’ll show you one way to get around this. However, I consider this an unacceptable flaw that deserves to be fixed before BizTalk Server 2013 is released.
For this demonstration, I used the adapter-friendly currency conversion service at Exchange Rate API. To get started, I created a new schema for “Invoice” and a property schema that held the values that needed to be passed to the send adapter.
Next, I built an orchestration that received this message from a (FILE) adapter, routed a GET request to the currency conversion service, and then multiplied the source currency by the returned conversion rate. In the orchestration, I routed the original Invoice message to the GET service, even though I knew I’d have to strip out the body before completing the request. Also, the Exchange Rate API service returns its result as text (not XML or JSON), so I set the response message type as XmlDocument. I then built a helper component that took in the service response message and returned a string.
public static class Utilities { public static string ConvertMessageToString(XLANGMessage msg) { string retval = "0"; using (StreamReader reader = new StreamReader((Stream)msg[0].RetrieveAs(typeof(Stream)))) { retval = reader.ReadToEnd(); } return retval; } }
Here’s the final orchestration.
After building and deploying this BizTalk project (with the two schemas and one orchestration), I created a FILE receive location to pull in the original invoice. I then configured a WCF-WebHttp send port. First, I set the base address to the Exchange Rate API URL, and then set an operation (which matched the name of the operation I set on the orchestration send port) that mapped to the GET verb with a parameterized URL.
I set those URL parameters by clicking the Edit button under Variable Mapping and choosing which property schema value mapped to each URL parameter.
This scenario was nearly done. All that was left was to strip out the body of message so that the GET wouldn’t fail. Fortunately, Saravana Kumar already built a simple pipeline component that erases the message body. I built the pipeline component, added it to a custom pipeline, and deployed the pipeline.
Finally, I made sure that my send port used this new pipeline.
With all my receive/send ports created and configured, and my orchestration enlisted, I dropped a sample file into a folder monitored by the FILE receive adapter. This sample invoice was for 100 Australian dollars, and I wanted the output invoice to translate that amount to U.S. dollars. Sure enough, the REST service was called, and I got back a modified invoice.
<ns0:Invoice xmlns:ns0="http://Seroter.BizTalkRestDemo"> <ID>100</ID> <CustomerID>10022</CustomerID> <OriginalInvoiceAmount>100</OriginalInvoiceAmount> <OriginalInvoiceCurrency>AUD</OriginalInvoiceCurrency> <ConvertedInvoiceAmount>103.935900</ConvertedInvoiceAmount> <ConvertedInvoiceCurrency>USD</ConvertedInvoiceCurrency> </ns0:Invoice>
So we can see that GET works pretty well (and should prove to be VERY useful as more and more services switch to a RESTful model), but you have to be careful on both the URLs you access, and the body you (don’t) send.
Scenario #2 Invoking a “DELETE” Command Via Messaging Only
Let’s try a messaging-only solution that avoids orchestration and calls a service with a DELETE verb. For fun, I wanted to try using the WCF-WebHttp adapter with the “single operation format” instead of the XML format that lets you list multiple operations, verbs and URLs.
In this case, I wrote an ASP.NET Web API service that defines an “Invoice” model, and has a controller with a single operation that responds to DELETE requests (and writes a trace statement).
public class InvoiceController : ApiController { public HttpResponseMessage DeleteInvoice(string id) { System.Diagnostics.Debug.WriteLine("Deleting invoice ... " + id); return new HttpResponseMessage(HttpStatusCode.NoContent); } }
With my REST service ready to go, I created a new send port that would subscribe directly on the input message and call this service. The structured of the “single operation format” isn’t really explained, so I surmised that all it included was the HTTP verb that would be executed against the adapter’s URL. So, the URL must be fixed, and cannot contain any dynamic parameter values. For instance:
To be sure, the scenario above make zero sense. You’d never really hardcode a URL that pointed to a specific transaction resource. HOWEVER, there could be a reference data URL (think of lists of US states, or current currency value) that might be fixed and useful to embed in an adapter. Nonetheless, my demos aren’t always about making sense, but about flexing the technology. So, I went ahead and started this send port (WITHOUT changing it’s pipeline from “passthrough” to “remove body”) and dropped an invoice file to be picked up. Sure enough, the file was picked up, the service was called, and the output was visible in my Visual Studio 2012 output window.
Interestingly enough, the call to DELETE did NOT require me to suppress the message body. Seems that Microsoft doesn’t explicitly forbid this, even though payloads aren’t typically sent as part of DELETE requests.
Summary
In these two articles, we looked at REST support in the BizTalk Server 2013 (beta). Overall, I like what I see. SOAP services aren’t going anywhere anytime soon, but the trend is clear: more and more services use a RESTful API and a modern integration bus has to adapt. I’d like to see more JSON support, but admittedly haven’t tried those scenarios with these adapters.
What do you think? Will the addition of REST adapters make your life easier for both exposing and consuming endpoints?
Nice post Richard, thanks.
Did you try Biztalk with OAuth, or have you seen anything regarding that topic. I’m trying not to build plumbing code…
Hi Christian. Given that BIzTalk 2013 works natively with the Service Bus (and ACS), I’d hope that you could use the ACS 2.0 support for OAuth http://msdn.microsoft.com/en-us/library/windowsazure/gg185937.aspx
Hi Richard,
Nice post. I have done some similar exploring and the BtsHttpUri mapping is actually quite simple. When your URL is invoked using GET or DELETE it will cause the adapter to put the corresponding operation in BTS.Operation and promote the content at the placeholders position into the property you can map in the Variable dialog.
Did you also notice that the GET receive method produces a context only message? You can connect the receive to an outgoing WebHTTP port without using the RemoveMessageBody Plc and just be routing properties.
Interesting, thanks Charles. Yes, it makes sense that an inbound GET results i a context-only message. I wonder what new BizTalk scenarios/tools will pop up as a result of these lightweight request messages.
Hi Richard,
We are experimenting scenarios with RESTful services (GET) consumed by BizTalk 2009 using custom wcf behavior. However, for some scenarios, we build our RESTful services with parameters. The ‘&’ sign is thus mandatory. I am very surprise and disappointed of this BizTalk 2013 beta limitation! Do you expect it to be a limitation on the CTP as well? In that case, BizTalk support for RESTful services would be very restrictive.
Hi Etienne, I hope this will be changed for the release as it is fairly common to see that symbol in REST services!
Hi all,
First of all, I don’t know if you’ve found this in the mean time but you can use the ‘&’ sign in your URL. However, you have to use ‘&’ as in: /currency?from=AUD&to=USD
I’ve tested it and it works perfectly.
Second, another issue that you might have encountered is that you can’t concatenate variables in your url. For instance you can’t use: /customer?id={customer_id}{specification} which is probably not often used but might be useful. It seems weird that you can’t do something as basic as concatenation there.
And last but not least: did somebody find an easy way to process JSON responses? Is there a hidden built-in JSON parser or XML-JSON converter in the adapter or will we have to create custom helper classes for the orchestration or custom pipeline components? I think this is a basic feature that should be added as many REST replies are in JSON.
It would be nice to have a checkbox: “Parse to XML” or something like that.
Thanks Henry. I just tried the “&” again, and while you can put that in the top “Address” box in the configuration window, you cannot add it to the “url mapping” section. I still get an error when I put one there, and no error once I remove it!
You can use the & sign, guys. The only thing you need to do is to ‘XML escape’ it.
The following should work : /currency?from=AUD&to=USD
Thanks Sam. I’ll try it with the escaping instead. Good call.
I’m sorry, I was trying to explain that you could use the XML escape character but did not notice that when submitting my message, the escaped character was processed and shown as the normal &. Thanks Sam for clarifying!
Hi Richard,
Thanks for the article! I considered it very useful for getting familiar with the WCF-WebHTTP-adapter.
I noticed, by the way, that it looks like the exchange rate API you used isn’t free (anymore). It looks like you have to take a subscription, before you can enjoy a 14 days free trial. Strange, right??
So instead I took the API at http://currencies.apps.grandtrunk.net/. You can also find it at Programmable Web. Because the syntax of the API is almost the same (same parameters, text response) as the one you used, only some minor modifications to the Send Port are needed (URL and no API key needed).
Best regards,
Lex
Hi,
Any plans to publish a JSON update?
Larry, I was thinking about it! It requires the use of a custom pipeline or component as BizTalk isn’t particularly JSON-friendly.
Hi Richard,
Good article. I have a requirement to make a rest call from BizTalk 2013 with the entire message body in the URL instead of one or two elements from the message. The GET request should look like htttp://temp.com/getdata?. Is there any way i can accomplish this using WCF-WebHttp adapter? If not is there any other way?
Correction for the above: The Get request should look like http://temp.com/GetData?Messagebodywithxmltags