Exploring REST Capabilities of BizTalk Server 2013 (Part 2: Consuming REST Endpoints)

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.

2012.11.19rest01

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.

2012.11.19rest02

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.

2012.11.19rest03

I set those URL parameters by clicking the Edit button under Variable Mapping and choosing which property schema value mapped to each URL parameter.

2012.11.19rest04

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.

2012.11.19rest05

Finally, I made sure that my send port used this new pipeline.

2012.11.19rest06

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:

2012.11.19rest08

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.

2012.11.19rest09

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?

Author: Richard Seroter

Richard Seroter is currently the Chief Evangelist at Google Cloud and leads the Developer Relations program. He’s also an instructor at Pluralsight, a frequent public speaker, the author of multiple books on software design and development, and a former InfoQ.com editor plus former 12-time Microsoft MVP for cloud. As Chief Evangelist at Google Cloud, Richard leads the team of developer advocates, developer engineers, outbound product managers, and technical writers who ensure that people find, use, and enjoy Google Cloud. Richard maintains a regularly updated blog on topics of architecture and solution design and can be found on Twitter as @rseroter.

24 thoughts

  1. 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.

    1. 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.

  2. 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.

    1. 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.

      1. 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!

      2. 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!

  3. 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

  4. 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?

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.