BizTalk Server 2013 Support for RESTful Services (Part 3/5)

By Nick Hauenstein

This post is the fifteenth in a weekly series intended to briefly spotlight those things that you need to know about new features in BizTalk Server 2013. It is also the third part of a five-part series on REST support in BizTalk Server 2013.

Last week’s post worked through how one would use BizTalk Server to host a RESTful endpoint that would support multiple “operations” (i.e., expose multiple resources). This week we’re going to be trying to do something quite the opposite – consume a RESTful endpoint (using the POST verb) that only represents a single resource (and as such will not require operation mapping). In the process we will deal with formatting a form encoded message, and customizing the outgoing message headers.

This Week’s Scenario

This week we will be working on a ridiculously fictional integration with a home grown finance suite which exposes a RESTful API using a ASP.NET WebAPI service with an implementation that looks something like this.

Essentially the story goes that as new sales happen, the amounts of those sales are aggregated by POSTing them to the MonthlySales resource. Once the data has been collected, the aggregate information can be requested by issuing a GET request to the same resource indexed by month number.

While this week’s scenario is especially painfully contrived, it does serve to allow me to demonstrate simple POST requests and some of the fun that might surround them.

Dealing with Form Values

Whenever you POST data, it is contained in some form within the body of the http request. In the case of ASP.NET WebAPI, it is expected that this data is url encoded. The end result of a request body should look something like this. In order to ensure that a sale message received by the BizTalk application can be translated into this format, we will need not only a map (to transform the message) but also a schema and pipeline (to translate the message from XML to a flat-file format).

In order to translate to a flat-file format, I used the flat-file schema wizard to define a simple flat-file schema that splits first on the ampersand (&), and then on the equals sign (=) to create a message that resembles the following:

image

The one thing that this schema does NOT take into account is the escaping of special characters. For those considerations, one would have to resort to logic within a map – which will not be something that we encounter this week.

After this schema has been defined, we need a pipeline that can create flat-file messages from any XML message that conforms to this schema (nothing special, just a text-book flat-file transmit pipeline):

image

In order to get the data from the sale message into the flat-file format called for, we need to use a map. Mapping back and forth between URL encoded form data and XML ultimately feels like an EDI mapping involving code pairs – you’re dealing with data that is identified by a sibling node. As a result, for digging deep into advanced mapping techniques using a schema similar to this, I would recommend the discussion of EDI code pairs in the book Pro Mapping in BizTalk Server 2009 (ignore the version number in the title – the book is excellent) as it will provide a nice introduction to techniques that can be used to make this manageable.

For my map, it was fairly straightforward. We need to take a single value from the sale message, and map it over into key=value format:

image

Configuring the WCF-WebHttp Adapter to POST Form Data

We’re at the point now where we have a way to take an XML message and convert it into a format that would live nicely within the body of an http request as form data (readable quite nicely by an ASP.NET WebAPI service). However, we do need to make sure that when the data is sent, the format is identified. In order to do that, we need to ensure that the Content-Type header is transmitted alongside the body with a value of “application/x-www-form-urlencoded”.

So how do we make that happen? Through the Messages tab of the adapter configuration:

image

We can finish off the configuration on the General tab. Here I’m showing an operation mapping that only intends to ever call a single operation. Since all of the information is passed within the body, we don’t need to do any building out of the URL, we don’t have any variable mapping from the context into the URL, or anything like that. As such, configuration becomes very simple – we only need to specify the HTTP method in the mapping field:

image

Validating the Request

So what message was generated by our send port? Well after a quick tweak to the URL to ensure that Fiddler would capture it appropriately, we see the following:

image

We can see the POST verb is being used, the Content-Type has been specified correctly, and the body contains the urlencoded content of the original sale message. After submitting a few similar requests (to the correct URL), we can verify that the messages indeed are received and aggregated appropriately by executing a GET request against the resource:

image

What’s next?

We’ve made it 3/5 of the way through this mini-series on the WCF-WebHttp adapter, and have quite a few new powers at our disposal, but there are still a few things missing that we will be tackling over the next few posts – namely the ability to read that wonderful JSON response (or any JSON data for that matter), and also the oft-neglected in sample code: authentication.

The end for now!

If you would like to access sample code for this blog post, you can find it on github.

BizTalk Server 2013 Support for RESTful Services (Part 2/5)

By Nick Hauenstein

This post is the fourteenth in a weekly series intended to briefly spotlight those things that you need to know about new features in BizTalk Server 2013. It is also the second part of a five-part series on REST support in BizTalk Server 2013.

Last week we started out with a bit of an overview of the WCF-WebHttp adapter that is behind the REST support in BizTalk Server 2013. This week, we will be looking at some simple scenarios around receiving RESTful requests.

The Scenario

For this week’s post I didn’t want to propose a scenario so complex that it would warrant a complex diagram. I will be designing a fairly simple API that will (1) accept an “order” message and respond with an acknowledgement (an “order status” message) through the use of an orchestration. It will also (2) archive the order to a FILE location in a pure messaging fashion. Finally it will (3) support a lookup of an order (for which I will be providing a canned response), through a separate operation on the same orchestration1.

In terms of how I want the world to interface with my service:

  • I want my API to be rooted at http://localhost/services/orderprocessing/
  • I want to expose the resource of /api/orders
    • I want to be able to POST a new order to /api/orders
    • I want to be able to lookup an order by issuing a GET to /api/orders/{order id here}

Defining My Messages

I am going to begin by defining the messages that will be used throughout. Until later in the series, we will be dealing with plain old XML messages, so that’s what I am using here. I have two message schemas Order.xsd, and OrderStatus.xsd. Whenever a client submits an Order message (Order.xsd) they will receive as an acknowledgement an Order Status message (OrderStatus.xsd). Whenever someone issues a GET request to /api/orders/{order id here}, they will also need to receive an Order Status message (OrderStatus.xsd) as a reply. However, in the case of the GET request, there will be no message body. Instead we will capture the information contained in the URL within the message context via the Property Schema (PropertySchema.xsd):

image image image

You may have noticed that I have distinguished a few fields. This will be for easier access within the orchestration later (though I am not actually using the Purchaser field).

Publishing My Service

At this point, I have a pretty good idea of how I want the service to act, and I also have some messages defined. I am in a good position now to publish the service. Unlike other services that we may publish within BizTalk, RESTful services will not have any associated metadata published. Which means, I could have walked all the way through the WCF Service Publishing wizard before even opening Visual Studio.

I should mention at this point that the WCF-WebHttp adapter operates only within an Isolated Host (i.e., it gets hosted in IIS instead of In-Process within a BizTalk Host Instance Service). If you want something different, you can still use WCF-Custom if you want to jump through hoops like crazy.

Let’s see what that experience is like for a RESTful service. It will start with the same dialog that you might be used to by now, but this time I am going to ensure that WCF-WebHttp is selected as the adapter:

image

Notice that the Enable on-premise metadata exchange option is grayed out. As mentioned before, there will be no metadata published, nor will there be a requirement for any tool to consume metadata. While consuming this RESTful service we will be working pretty close to the HTTP metal, and will not always have a lot of tooling at our disposal to “poof” out a happy ready-to-go client (depending on where we are consuming it from of course).

After selecting the message exchange pattern on the following page of the wizard (one-way / request-response) you will be taken to the last page in the wizard that matters:

image

No matter what you do on this page, you will end up with a service hosted at Service1.svc (yuck!) under the virtual directory that you have specified.

Making the Endpoint URL Pretty: Down with Service1.svc

I don’t know about you, but I will not be able to continue knowing that I have an endpoint named Service1.svc. So let’s make that pretty (and also align with our requirements set out above) before continuing.

In order to do that, I am going to be using the URL Rewrite 2.0 module for IIS. You can get it fairly easily through the Web Platform Installer:

image

After getting that installed, I went over to my virtual directory in IIS, and clicked on the Features View tab and fired up the URL Rewrite settings:

image

Next, I added a rule that would rewrite (imagine a redirect that is invisible to the client) a request aimed at *api* so that it would point at *Service1.svc*. Of course, this definition is using Regular Expressions instead of simple wildcards, so it looks a little something like this:

image

image

With IIS all configured (if you’re trying to follow along, make sure the App Pool is happy to do BizTalk processing first), I decided to move on to the configuration of the Receive Location.

Configuring the WCF-WebHttp Adapter for Receiving Messages

The WCF Service Publishing Wizard has already created a Receive Port and a Receive Location for the service. Diving into that Receive Location, and examining the adapter settings, you will find that the receive side looks fairly similar, in terms of the operation and variable mapping, to the send side. For the purposes of the scenario, I defined two separate operations – one uses a GET, while the other uses a POST:

image

The GET operation requires a variable to be included within the URL. In order to access that variable in a meaningful fashion, you can use the Variable Mapping section to define a mapping to a context property in the message:

image

Unfortunately, the data from the URL does not actually get Promoted into the context, it is instead Written to the context. This means that if you attempt to route based on the OrderId property, you might be faced with a routing error that reveals a message context looking something like this:

image

The other interesting thing about this GET request is that it will force us, at the moment, to use a PassThruReceive pipeline (since an XMLReceive will complain about the empty message body). This will prevent property promotion of data from our XML Order message above. For now, we will accept this and move on (as this will be dealt with later in this same series).

Subscribing to a REST Request (Messaging)

In order to archive the orders as they are received, I am going to use a very simple mechanism: a Send Port with a FILE adapter. That’s really it – a pure messaging solution to the problem.

In order to subscribe to the message, I will be using the BTS.OperationName property to specify that I am interested in messages where the Operation is POST_Order:

image

Subscribing to a REST Request (Orchestration)

On the Orchestration side, I made not the greatest choice and doubled-up both operations in a single Orchestration with some hard-coded filters on the Receive shapes. You can see the resulting structure of the orchestration below:

image

The branch on the left of the Listen shape begins with a Receive listening for an order message. Since the message will not have been through an XMLReceive pipeline, the message bound to that receive shape is the generic “XmlDocument” type (which will also end up working for a completely empty message). As a result, the first step under that branch is to take that more generic XmlDocument and jam it into another message variable that is a strongly typed order message. From there we generate an Order Status message (via Transform) which indicates that the order is in the “Pending” status.

The right branch is a little more interesting. This is what happens whenever we have a GET request come in. In order to read the data from the request, we have to muck around with the context. In order to create new messages, we can’t really use a transform since we don’t have a meaningful source message, so we are stuck with only the Message Assignment shape at our disposal.

Here’s the expression behind the magic in creating the (canned response) Order Status message:

image

Consuming the Service (GET Request)

Now that we have all of the pieces, let’s put it to the test! I’m going to do the first test using Internet Explorer. Why? Because it can issue a clean GET request without knowledge of the service or its specific implementation – it’s a good test to do in this case.

Issuing the request directly to the rewritten URL yields the following happy response:

image

Consuming the Service (POST Request)

In order to issue the POST request, it’s not going to be as simple as typing a URL in my browser. Additionally, the service is expecting a pretty specific message, so I will probably need to reference the schema in some way.

The approach I am taking here will be to use the xsd.exe utility to generate a nice C# class for my schema, serializing an instance of my type, and using the HttpClient class (find it in the Microsoft.AspNet.WebApi.Client NuGet package) to POST my newly created string to the service.

Tossed into a console app, it looks a little something like this:

Order order = new Order();
order.Id = "12345";
order.Purchaser = "Alice Bobson";
order.Items = new OrderItem[] { new OrderItem() { Id = "12345", Qty = 1, Price = 5.95M } };

XmlSerializer ser = new XmlSerializer(typeof(Order));
MemoryStream outputStream = new MemoryStream();
ser.Serialize(outputStream, order);

StringContent serializedOrder = new StringContent(Encoding.Unicode.GetString(outputStream.ToArray()),
                                                    Encoding.Unicode, "application/xml");

Console.WriteLine("Submitting order...");

HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost/services/orderprocessing/");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));

HttpResponseMessage response = client.PostAsync("api/orders/", serializedOrder).Result;

if (response.IsSuccessStatusCode)
{
    Console.WriteLine("Request was successful.");
    Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
else
{
    Console.WriteLine("Request failed.");
}

Console.ReadLine();

The end result of executing that code, is this beauty of a response:

image

I <3 rest

On a more serious note (not talking about HTTP, services, or anything of that nature), I really do enjoy resting – especially sleep. As a result, I’m going to call it quits for this week, and will pick back up with the other side of this equation (POSTing data to another service) next week.

While you’re here, check out our training calendar to see if there are any classes coming up that might be able to help you sharpen your skills.

If you would like to access sample code for this blog post, you can find it on github.

1 This is purely because I am too lazy to create and document two full orchestrations right now.