JSON Schemas in BizTalk Server 2013 R2

This is the third in a series of posts exploring What’s New in BizTalk Server 2013 R2. It is also the first in a series of three posts covering the enhancements to BizTalk Server’s support for RESTful services in the 2003 R2 release.

In my blog post series covering the last release of BizTalk Server 2013, I ran a 5 post series covering the support for RESTful services, with one of those 5 discussing how one might deal with JSON data. That effort yielded three separate executable components:

  1. JSON to XML Converter for use with the WFX Schema Generation tool
  2. JSON Decoder Pipeline Component (JSON –> XML)
  3. JSON Encoder Pipeline Component (XML –> JSON)

It also yielded some good discussion of the same over on the connectedcircuits blog, wherein some glitches in my sample code were addressed – many thanks for that!

All of that having been said, similar components in one form or another are now available out of the box with BizTalk Server 2013 R2 – and I must say the integrated VS 2013 tooling blows away a 5 minute WinForms app. In this post we will begin an in-depth examination of this improved JSON support by first exploring the support for JSON Schemas within a BizTalk Server 2013 R2 project.

How Does BizTalk Server Understand My Messages?

All BizTalk Server message translation occurs at the intersection between 2 components: (1) A declarative XSD file that defines the model of a given message, with optional inline parsing/processing annotations, and (2) an executable pipeline component (usually within the disassemble stage of a receive pipeline or assemble stage of the send pipeline) that reads the XSD file and uses any inline annotations necessary to parse the source document.

This is the case for XML documents, X12, EDIFACT, Flat-file, etc… It only logically follows then that this model could be extended for JSON. In fact, that’s exactly what the BizTalk Server team has done.

JSON is an interesting beast however, as there already exists a schema format for specifying the shape of JSON data. BizTalk Server prefers working with XSD, and makes no exception for JSON. Surprisingly this XSD looks no different than any other XSD, and contains no special annotations to reflect the message being typically represented as JSON content.

What Does a JSON Schema Look Like?

Let’s consider this JSON snippet, which represents the output of the Yahoo! Finance API performing a stock quote for MSFT:

image

This is a pretty simple instance, and it is also an interesting case because it has a null property Ask, as well as a repeating record quote that does not actually repeat in this instance. I went ahead and saved this snippet to the worst place possible – my Desktop – as quote.json and then created a new Empty BizTalk Server Project in Microsoft Visual Studio 2003 (with the recently released Update 3).

From there I can generate a schema for this document by using the Add New Items… context-menu item for the project within Solution Explorer. From there, I can choose JSON Schema Wizard in the Add New Item dialog:

image

The wizard looks surprisingly like the Flat-file schema wizard, and it looks like quite a bit of that work might have been lifted and re-purposed for the JSON schema wizard. What’s nice about this wizard though, is that this is really the only page requiring input (the previous page is the obligatory Welcome screen) – so you won’t be walking through the input document while also recursively walking through the wizard.

image

Instead the wizard makes some core assumptions about what the schema should look like (much like the WFX schema generator). In the case of this instance, it’s not looking so great. Besides from essentially every single element being optional in the schema, the quote record was not set as having a maxOccurs of unbounded – though this should really be expected given that our input instance gave no indication of this. However, maybe you’re of the opinion that the wizard may have been written to infer that upon noticing it was a child of a record with a plural name – which might be an interesting option to see.

image

Next the Ask record included was typed as anyType instead of decimal – which again should be expected given that it was simply null in the input instance. However, maybe this could be an opportunity to add pages to the wizard asking for the proper type of any null items in the input instance.

Essentially, it may take some initial massaging to get everything in place and happy. After tweaking the minOccurs and maxOccurs, as well as types assigned to each node, I decided it would be a good time to ensure that my modifications would still yield a schema that would properly validate the input instance I provided to the wizard.

How do We Test These Schemas Or Validate Our JSON Instances?

Quite simply, you don’t. At least not using the typical Validate Instance option available in the Solution Explorer context-menu for the .xsd file. Instead this will require a little bit of work in custom-code.

Where am I writing that custom code? Well right now I’m on-site in Enterprise, Alabama teaching a class that involves a lot of automated testing. As a result, I’m in the mood for writing some unit tests for the schema – which also means updating the project properties so that the class generated for the schema derives from TestableSchemaBase and adds a method we can use to quickly validate an instance against the schema.

image

It also means adding a new test project to the solution with a reference to the following assemblies:

  • System.Xml
  • C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\PublicAssemblies\Microsoft.BizTalk.TOM.dll
  • C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\PublicAssemblies\Microsoft.BizTalk.TestTools.dll
  • C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\PublicAssemblies\Microsoft.XLANGs.BaseTypes.dll
  • Newtonsoft.Json (via Nuget Package)

That’s not all the setup required unfortunately. I still have to add a new TestSettings file to the solution, ensure that deployment is enabled, that it is deploying the bolded Microsoft.BizTalk.TOM.dll assembly above, and that it is configured to run tests in a 32-bit hosts. From there I need to click TEST > Test Settings > Select Test Settings File, to select the added TestSettings file.

image

image

image

image

With all the references in place and the solution all setup, I’ll want to bring in the message instance(s) to validate. In order to ensure that the test has access to these items at runtime, I will add the applicable DeploymentItem attribute to each test case that requires one.

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using System.IO;
using System.Xml;

namespace QuickLearn.Finance.Messaging.Test
{
    [TestClass]
    public class ServiceResponseTests
    {

        [TestMethod]
        [DeploymentItem(@"Messages\sample.json")]
        public void ServiceResponse_ValidInstanceSingleResultNullAsk_ValidationSucceeds()
        {

            // Arrange
            ServiceResponse target = new ServiceResponse();
            string rootNode = "ServiceResponse";
            string namespaceUri = "http://schemas.finance.yahoo.com/API/2014/08/";
            string sourceDoc = Path.Combine(TestContext.DeploymentDirectory, "sample.json");
            string sourceDocAsXml = Path.Combine(TestContext.DeploymentDirectory, "sample.json.xml");

            ConvertJsonToXml(sourceDoc, sourceDocAsXml, rootNode, namespaceUri);

            // Act
            bool validationResult = target.ValidateInstance(sourceDocAsXml, Microsoft.BizTalk.TestTools.Schema.OutputInstanceType.XML);

            // Assert
            Assert.IsTrue(validationResult, "Instance {0} failed validation against the schema.", sourceDoc);

        }

        public void ConvertJsonToXml(string inputFilePath, string outputFilePath,
            string rootNode = "Root", string namespaceUri = "http://tempuri.org", string namespacePrefix = "ns0")
        {
            var jsonString = File.ReadAllText(inputFilePath);
            var rawDoc = JsonConvert.DeserializeXmlNode(jsonString, rootNode, true);

            // Here we are ensuring that the custom namespace shows up on the root node
            // so that we have a nice clean message type on the request messages
            var xmlDoc = new XmlDocument();
            xmlDoc.AppendChild(xmlDoc.CreateElement(namespacePrefix, rawDoc.DocumentElement.LocalName, namespaceUri));
            xmlDoc.DocumentElement.InnerXml = rawDoc.DocumentElement.InnerXml;

            xmlDoc.Save(outputFilePath);
        }

        public TestContext TestContext { get; set; }
    }
}

What Exactly Am I Looking At Here?

Here in the code we’re converting our JSON instance first to XML using the Newtonsoft.Json library. Once it is in an XML format, it should (in theory at least) conform to the schema definition generated by the BizTalk JSON Schema Wizard. So from there, we take output XML, and feed it into the ValidateInstance method of the schema to perform validation.

The nice thing about doing it this way, is that you will not only get a copy of the file to use within the automated test itself, but you can also use the file generated within the test in concert with the Validate Input Instance option of the schema for performing quick manual verifications as well.

After updating the schema, it looks like it’s going to be in a usable state for consuming the service:

Screenshot of final code

Coming Up Next Week

Next week will be part 2 of the JSON series in which we will test and then use this schema in concert with the tools that BizTalk Server 2013 R2 provides for consuming JSON content.

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)

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

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

    This post is the thirteenth 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 first part of a five-part series on REST support in BizTalk Server 2013.

    BizTalk Server 2013 is trying to make BizTalk Server not only the application/integration server for the enterprise, but also for the Cloud. Here we’re referring specifically to those Software-as-a-Service solutions provided by 3rd party organizations in an elastic fashion – usually exposing an API in the form of REST endpoints.

    In this post, we will begin to explore the REST support in BizTalk Server 2013 in an overview fashion. We will then continue our exploration with a series of posts that cover common scenarios (Receiving data, POST-ing data, JSON en/decoding, and finally OAuth authentication).

    How Do We Do REST in BizTalk Server 2013?

    We do REST through BizTalk’s new WCF-WebHttp adapter. This adapter really is just another WCF adapter (like the SFTP adapter). It can be used on the Send or Receive side, in both one-way and two-way configurations.

    image

    In this case though, it is really clear that WCF is the underlying technology. Like all other service operations within BizTalk, we are exposed to operation mapping (the mapping of operations within orchestrations to actions in the service). However with the operation mappings in the WCF-WebHttp adapter, we don’t specify WCF actions so much as resources that we want to request (since it’s all just plain-old HTTP on the other end):

    image

    Do I Need a Dynamic Send Port To Do a GET?

    The operation mapping shown above begs the question of how a GET request like this would work. Here we’re showing some sort of weather service that is providing temperature readings on a postal code basis. In order to make a request for the readings, one would have to access a URL that would change on a per postal code basis (i.e., the endpoint address changes).

    Typically to accomplish something like sending to a dynamic address, one would use a dynamic send port. In the case of the WebHttp adapter, however, we get to specify variables within the path (which is shown in template form). In the screenshot above, we used the {postalCode} variable. Clicking the Edit button under Variable Mapping will lead us to the following screen:

    image

    Here we can see that in order to specify those variables, we simply pull from the context of the message traveling through the port. In this case we are grabbing the value for the {postalCode} part of the path from the Context Property named ZipCode.

    Since most of the time that we are using the GET method, we don’t want to include a message (really it’s a request for a resource, and the dynamic part is the URL, not the body of the request), we can suppress the body using the Suppress Body for Verbs, and specifying the methods for which we want to not include a request body.

    image

    What Don’t I Get?

    So far looking through the settings, it looks like we have a pretty good story around creating RESTful requests. However, we don’t have everything out of the box that we need to consume every single RESTful API out there.

    You will still have to provide things like the following:

    • Encoding/decoding support (e.g., for JSON encoded messages)
    • WCF extensions for performing authentication (e.g., OAuth)
    • Schemas representing the requests/responses

    These are some of the things that we will be covering within this series, so stay tuned over the next few weeks!

    Do I Need BizTalk Server 2013 To Make this Happen?

    While the adapter is new in BizTalk Server 2013, the underlying mechanism that makes it work is the WCF WebHttpBinding, which was around during the BizTalk Server 2010 timeframe. I’ve actually had people complain at me while explaining the WCF-WebHttp adapter as a new feature because of this.

    Does that mean you can get it all up and running using something like the WCF-Custom adapter? Yes, and no. You can technically make it function with some additional legwork (e.g., as seen here), but you’re not going to get as smooth as an experience as you will see with BizTalk Server 2013 – it really feels cobbled together without having BizTalk Server 2013 at your disposal.

    Coming Up Next

    Next week I will be talking through the receive side of this story as we see how to host a RESTful endpoint in BizTalk Server 2013. Until then, take care (and take our classes)! Smile