REST Start Kit for BizTalk Server

Listen with webReader
Published 28 May 12 12:45 AM | wmmihaa

The REST Start Kit for BizTalk Server is about providing support for GET, POST, PUT and DELETE operation, for both Receive and Send ports together with support for both XML and JSON.

In a former post, I showed how to expose REST services from BizTalk. However I never got it to work for GET operations and did not cover consuming other REST services through Send Ports. Consuming REST services was however greatly covered by Nitin Mehrotra in his post “Invoke ReSTful Web Services with BizTalk Server 2010”. In fact I’ve included Nitins code in this solution to compete the REST Start Kit for BizTalk Server.

Is this post interesting to me?

We are seeing a broader diversity among clients, hosted on various smart devices, running on different runtimes. Commonly among all these, is that applications are becoming commodity with a relatively short life-cycle. These applications needs to be rapidly developed using frameworks that can be re-used on other platforms. These and other factors are reasons we see a broad adoption of HTML5 and JavaScript today.

When developing these kind of applications, REST-based services are the preferred choice by far. Not only because it’s easy to consume using JQuery (resource orientated JavaScript library), but equally important is the fact that REST is lightweight. -Bandwidth is not infinite on mobile devices!

Is this important to BizTalk? Yes it is! BizTalk Server is Microsoft’s middleware platform. And as such it should manage REST. Arguably, many web-based application are built together with the service layer in the same application. But what happens when the client needs to access a back-end system like SAP or Oracle EBS? BizTalk can handle these with ease, however it can’t bridge them to REST. 

I’ve tried my best to make the start kit easy to use. However I do realize that many of the topics mentioned in the post are outside the comfort zone for many. But if you only care about HOW to use it, just skip the “How it works” section of the post.

What is REST?

I assume you already know what REST is, but never the less… Representational state transfer (REST) is a light weight protocol introduced by Roy Fielding around the year 2000. REST exposes services over HTTP, and can receive the request either through the URI, as in the case of a GET or DELETE operation, or through the payload (POST and PUT).

HTTP verbs are essential to REST, as REST is focused on entities or resources. For instance, you wouldn’t expose a DeleteCustomerOrder method using REST. Instead you’d let the client access your recourses using the URI, Eg http://somedomain.com/Customers(1234)/Orders. If the user was to delete an Order (with an id of 5678), he or she would call http://somedomain.com/Customers(1234)/Orders(5678) using the HTTP DELETE verb. Using the GET verb, would return the actual order (given that it was not already deleted). If the resource was deleted (or never created), the user should receive a 404 status code.

POST (and PUT) works a bit different, as it receives it’s request through the payload. This behavior is similar to SOAP (which only uses POST), however REST does not require a specific format (as opposed to SOAP which uses the SOAP envelope). In fact, you don’t even have to use XML. Arguably, most clients call REST services using the JSON format.

If you don’t know about JSON, it’s a lightweight data format, commonly used by JavaScript and JQuery. Part from being less verbose then XML, it can be parsed to an object on the client which makes it easier to navigate (as oppose to using XPath).

As such, REST is all about HTTP, and works very much like the architectural principles of the World Wide Web. This is not an accident, as Roy Fielding was one of the principal authors of the HTTP specification.

Many more things could (and should) be said about REST (and RESTFul services), but this is not the place. However, it’s important to point out the challenges we face using BizTalk:

1. BizTalk requires a Message!

This is somewhat problematic as all parameters for a GET or DELETE request is passed along with the URI, not the payload. Because of this, we need to intercept the request and create a “real” message using the parameters passed on by the URI. Using a dynamic URI’s reveals yet an other challenge, as URI’s are generally of a static nature for BizTalk. This is where the WebHttpBinding comes in to place, as it let’s us define a base URI which our service (Receive Location) will listen to, regardless of what proceeds the base URI, Eg http://somedomamin.com/Customers(1234)

2. BizTalk only accepts POST!

This was the most difficult problem to solve, and I’ll get more into detail on this later. But the basic principle is that upon creating the message described before, it will add necessary meta data to the message to let BizTalk think this is a POST message.

3. BizTalk only understand XML!

If the consumer sends a GET request to the service, it also passes along information in the HTTP header, letting us know what format is expected. This is done through the “Accept” header, and could be either “application/xml” or “application/json” (there are others, but xml and json are the only supported ones using the REST Start Kit).

In case of a GET request, the outgoing message will get converted from XML to JSON using JSON.Net. If the consumer sends a POST request, the header could state: Content-Type: application/json. If this is the case, the incoming request will also be converted.

How it works

To make use of the REST Start Kit for BizTalk you need to expose your service or consume another REST service using the WCF-Custom adapter with the binding set to WebHttpBinding. In addition to selecting the binding, you also need to add a behavior; BizTalkRESTRequestHandler for the Receive Location and BizTalkRESTTransmitHandler for the Send port. These behaviors takes care of underlying pluming needed to make BizTalk accept REST based messages. This is all you have to do.

Exposing REST services (Receive Locations)

GET and DELETE

Regardless of what HTTP verb is used, BizTalk only exposes one usable method, – the “TwoWayMethod”. This is because BizTalk does not really care about the actual message until it hits the pipeline. The TwoWayMethod does however care about the HttpRequestMessageProperty.Method to be “POST”.

In order to send anything but a POST request to BizTalk, we need to intercept the message and convert it to a POST, or create a new message (GET & DELETE) and set the HttpRequestMessageProperty.Method to “POST”. This action needs to be done in the SelectOperation method of an IDispatchOperationSelector behavior. As we need to use the WebHttpBinding, the behavior I’ve created inherits from WebHttpDispatchOperationSelector.

As said before, a GET or DELETE request passes it’s parameters through the URI. You may have a base URI (declared on the Receive Location) set to http://localhost:8080/MyService while the consumer may call your service using http://localhost:8080/MyService/Bookings/2012/11, expecting all bookings from November 2012. I this case the BizTalkRESTRequestHandler behavior parses the URI and passes a BizTalkWebHttpRequest message to BizTalk that would look like this:

<ns0:bizTalkWebHttpRequest 
  method="GET" 
  xmlns:ns0="http://bLogical.RESTSchemas.BizTalkWebHttpRequest/1.0">
  <ns0:params>
    <ns0:param>2012</ns0:param>
    <ns0:param>11</ns0:param>
  </ns0:params>
</ns0:bizTalkWebHttpRequest>

On the other hand, the user might use a bit more complex URI such as: http://localhost:8080/MyService/Employees?firstname=Caren&lastname=Smith  

In this case you need to instruct the behavior how to parse the URI. If you’ve ever created a REST service using only WCF, you’re probably familiar to the UriTemplate class, which is also used with the BizTalkRESTRequestHandler behavior. In the sample above, the UriTemplate could be: 
Employees?firstname={fname}&lastname={lname} 

Which in turn would give you BizTalkWebHttpRequest looking like this:

<ns0:bizTalkWebHttpRequest 
  method="GET" 
  xmlns:ns0="http://bLogical.RESTSchemas.BizTalkWebHttpRequest/1.0">
  <ns0:params>
    <ns0:param name="fname">Caren</ns0:param>
    <ns0:param name="lname">Smith</ns0:param>
  </ns0:params>
</ns0:bizTalkWebHttpRequest>

Lastly, if the consumer requires an XML formatted response, the response from BizTalk will be sent straight back to the consumer. However, if the user expects JSON, the response need to be parsed. The DispatchOperationSelector behavior, described above, is only executed on the incoming request, so we need to add an other behavior, –a IDispatchMessageInspector to handle the outgoing response. This behavior is called BizTalkRESTResponseHandler and is added by the BizTalkRESTRequestHandler. In that sense it’s internal and never exposed to you. Never the less, an IDispatchMessageInspector exposes two methods; AfterReceiveRequest and BeforeSendReply. The incoming header is added to the operation context in the  AfterReceiveRequest method, and if the “Accept” parameter is set to “application/json”, the response is converted to JSON and sent back, along with the WebBodyFormatMessageProperty set to WebContentFormat.Json.

PUT and POST

If the client sends a POST or PUT request with a content type set to “application/xml”, nothing is done but passing the message to BizTalk. Only it the content type is set to “application/json”, it is then parsed to XML using JSON.Net. If you expect a message to match a BizTalk generated schema like this:

<ns0:Tweet xmlns:ns0="http://yourns.Tweet">
  <Author>wmmihaa</Author>
  <Text>XML Rocks!</Text>
</ns0:Tweet>

…the JSON message needs to included the namespace as:

{"ns0:Tweet":{"@xmlns:ns0":"http://yourns.Tweet","Author":"wmmihaa","Text":"XML Rocks!"}}

Also, all JSON properties will be parsed as Xml Elements, not Attributes!

Consuming REST services (Send Ports)

As I said before, I’ve “borrowed” the consuming part from Nitin Mehrotra's sample, and added support for POST and PUT. To consume a REST service from BizTalk, the experience is pretty much the same as when exposing a service using a Receive Location. Set the Send Port Transport to WCF-Custom and the binding to WebHttpBinding. As with the Receive Location, we also need to add a behavior, - this time the BizTalkRESTTransmitHandler. This is a IClientMessageInspector. The actions of this behavior differs depending on the SOAP Action Header which you state in the WCF-Custom Transport Properties:

image   

GET and DELETE

To consume a REST service you have to pass a BizTalkWebHttpRequest message to the adapter.

<ns0:bizTalkWebHttpRequest 
  method="GET" 
  uriTemplate="/Events/{id}" 
  xmlns:ns0="http://bLogical.RESTSchemas.BizTalkWebHttpRequest/1.0">
  <ns0:params>
    <ns0:param name="id">123</ns0:param>
  </ns0:params>
  <ns0:headers>
    <ns0:header name="Content-Type">application/xml</ns0:header>
  </ns0:headers>
</ns0:bizTalkWebHttpRequest>

The UriTemplate together with your parameters and the Send Port URI, will make up the actual To URI of the message. For instance, if the Send Port URI is set to http://somedomain.com the message above would be sent to http://somedomain.com/Events/123.

The response is at this moment never parsed, since most REST services does respond XML if asked to…

POST and PUT

Except for adding necessary headers, the POST and PUT request does very little. Keep in mind though, you will always post a message to the URI set on the Send Port. You may find it tempting to use the same Send Port for all calls to a particular REST service, and although this will work for GET and DELETE, it wont work for POST and PUT. This is because the behavior has no knowledge of your intentions other than the payload. I could have solved this using SOAP Action Headers or some promoted property, but I didn’t… (sorry). 

How to use it

1. Download the bits from CodePlex.

The solution has four projects:

bLogical.BizTalk.RESTBehavior Includes the three behaviors:
- BizTalkRESTRequestHandler
- BizTalkRESTResponseHandler
- BizTalkRESTTransmitHandler
bLogical.BizTalk.RESTBehavior.Setup Installs the bLogical.BizTalk.RESTBehavior assembly to the Global Assembly Cache
bLogical.RESTSchemas Includes the BizTalkWebHttpRequest schema
BizTalkSampleApplication Includes six demo orchestrations and bindings.
ExternalSampleApplication This is a sample REST service used used in the Send Port of the BizTalkSampleApplication

2. Register the behavior

In order to see the behaviors in the Select Behavior Extension dialog you need to register the behaviors. This can be done in different places such as in the machine.config or the BTSNTSvc(64).exe.config file. However I find it more convenient to set it on the Receive- and Send handler in the BizTalk Administration Console, as you’d otherwise need to update the config files on all BizTalk machines (given you have more then one)

To do this, select the WCF-Custom adapter under Platform Settings –> Adapters in the BizTalk Administration Console. Double-click the Receive Handler and click the Properties button. Then click the Import button and browse to the WCF-Custom.BindingsExtension-ReceiveHandler.config found in both the solution folder and the installation folder. Repeat the steps for the Send handler using the WCF-Custom.BindingsExtension-SendHandler.config file.

SNAGHTML16ea3c8b

If you want to register the behaviors in the machine.config file(s), just copy the behavior extensions to the <behaviorExtensions> element in the appropriate files.

3. Install the BizTalkWebHttpRequest schema

The BizTalkWebHttpRequest is part of the bLogical.RESTSchemas project. Update the Application Name in the project properties, and deploy it to BizTalk.

4. Use the behaviors

Receive

  1. Create a two-way Receive Port and Receive Location
  2. Set the Transport to WCF-Custom
  3. Set the URI to something like http://localhost:9090/MyService, and select the webHttpBinding in the Binding tab
  4. Select the Behavior tab, and right-click the EndpointBehavior node on the left, and select Add extension
  5. Select the BizTalkRESTRequestHandler

SNAGHTML16fae3c2

6.  Set the UriTemplate to match your expected incoming request. You can have multiple UriTemplates delimited using a pipe, eg

/Person/id={pId}| /Person/firstname={fname} | /Person/lastname={lname}.

This would make your service accept incoming GET or DELETE request like these:

http://localhost:8080/myservice/Person/id=123
http://localhost:8080/myservice/Person/fistname=Caren
http://localhost:8080/myservice/Person/lastname=Smith

SNAGHTML16ff5401

Send

  1. Create a new Static Solicit-Response Send Port
  2. Set the Transport to WCF-Custom
  3. Click the Configure button and set the URI to the base URI of the service. Eg http://externalservice/service.svc. Select the webHttpBinding in the Binding tab
  4. Select the Behavior tab, and right-click the EndpointBehavior node on the left, and select Add extension
  5. Select the BizTalkRESTTransmitHandler from the list of extensions

5. Install and use the Sample Application

The BizTalkSampleApplication project has six samples:

ConsumeDELETE Makes a DELETE request to an external REST service (ExternalSampleApplication)
ConsumeGET Makes a GET request to an external REST service
ConsumePOST Makes a POST request to an external REST service
ExposeDELETE Receives an incoming DELETE request
ExposeGET Receives an incoming GET request
ExposePOST Receives an incoming POST request

The BizTalkSampleApplication is deployed to an appplication with the same name. The bindings file are included in the project. Before you try out the Consume* scenarios, make sure you’ve started the ExternalSampleApplication (just right-click the RESTService.svc file and select View in browser).

After you’ve deployed the solution to BizTalk, you need to redirect all FILE ports to the FILEDROP folder (part of the zip file)

All Consume* samples uses the same Receive Location; ReceiveConsumeREST and submits the message to the RESTService.svc in the ExternalSampleApplication.

To test the ExposeGET sample, you can use the browser and hit http:localhost:9999/Events/id=123 (any number will do)

To test the ExposeDELETE and ExposePOST you’ll need to use some other tool like Fiddler.

SNAGHTML171d0630 

To use the sample with Fiddler:

  1. Select the Composer tab
  2. Select the Verb and set the URI
  3. Set the Request Headers (sample file included in the solution)
  4. When testing POST, generate an instance of the Event schema in the BizTalkSampleApplication or copy the content from the Event_output.xml file in the FILEDROP folder.

That’s it. Let me know if you run into any issues. If you find it useful TWEET it!

HTH

//Mikael

Filed under: , , , ,

Comments

No Comments

This Blog

News

    MVP - Microsoft Most Valuable Professional BizTalk User Group Sweden BizTalk blogdoc

    Follow me on Twitter Meet me at TechEd

    Visitors

    Locations of visitors to this page

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

Syndication