Exploring REST Capabilities of BizTalk Server 2013 (Part 1: Exposing REST Endpoints)

The BizTalk Server 2013 beta is out there now and I thought I’d take a look at one of the key additions to the platform. In this current age of lightweight integration and IFTTT simplicity, one has to wonder where BizTalk will continue to play. That said, a clean support of RESTful services will go a long way to keeping BizTalk relevant for both on-premises and cloud-based integration scenarios. Some smart folks have messed around with getting previous version of BizTalk to behave RESTfully, but now there is REAL support for GET/POST/PUT/DELETE in the BizTalk engine.

I decided to play with two aspects of REST services and BizTalk Server 2013: exposing REST endpoints and consuming REST endpoints. In this first post, I’ll take a look at exposing REST endpoints.

Scenario #1: Exposing Synchronous REST Service with Orchestration

In this scenario, I wanted to use the BizTalk-provided WCF Service Publishing Wizard to generate a REST endpoint. Let’s assume that I want to let modern web applications send new “account” records into our ESB for further processing. Since these accounts are associated with different websites, we want a REST service URL that identifies which website property they are part of. The simple schema of an account looked like this:

2012.11.12rest01

I also added a property schema that had fields for the website property ID and the account ID. The “property ID” node’s source was set to MessageContextPropertyBase because its value wouldn’t exist in the message itself, but rather, it would solely exists in the message context.

2012.11.12rest02

I could stop here and just deploy this, but let’s explore a bit further. Specifically, I want an orchestration that receives new account messages and sets the unique ID value before returning a message to the caller. This orchestration directly subscribes to the BizTalk MessageBox and looks for any messages with a target operation called “CreateAccount.”

2012.11.12rest03

After building and deploying the project, I then started up the WCF Service Publishing Wizard. Notice that we can now select WCF-WebHttp as a valid source adapter type. Recall that this is the WCF binding that supports RESTful services.

2012.11.12rest04

After choosing the new web service address, I located my new service in IIS and a new Receive Location in the BizTalk Engine.

2012.11.12rest05

The new Receive Location had a number of interesting REST-based settings. First, I could choose the URL and map the URL parameters to message property (schema) values. Notice here that I created a single operation called “CreateAccount” and associated with the HTTP POST verb.

2012.11.12rest06

How do I access that “{pid}” value (which holds the website property identifier) in the URL from within my BizTalk process? The Variable Mapping section of the adapter configuration lets me put these URL values into the message context.

2012.11.12rest07

With that done, I bound this receive port/location to the orchestration, started everything up, and fired up Fiddler. I used Fiddler to invoke the service because I wanted to ensure that there was no WCF-specific stuff visible from the service consumer’s perspective. Below, you can see that I crafted a URL that included a website property (“MSWeb”) and a message body that is missing an account ID.

2012.11.12rest08

After performing an HTTP POST to that address, I immediately got back an HTTP 200 code and a message containing the newly minted account ID.

2012.11.12rest09

There is a setting in the adapter to set outbound headers, but I haven’t seen a way yet to change the HTTP status code itself. Ideally, the scenario above would have returned an HTTP 202 code (“accepted”) vs. a 200. Either way, what an easy, quick way to generate interoperable REST endpoints!

 

Scenario #2: Exposing Asynchronous REST Service for Messaging-Only Solution

Let’s do a variation on our previous example so that we can investigate the messages a bit further. In this messaging-only solution (i.e. no orchestration in the middle), I wanted to receive either PUT or DELETE messages and asynchronously route them to a subsequent system. There are no new bits to deploy as I reused the schemas that were built earlier. However, I  did generate a new, one-way WCF REST service for getting these messages into the engine.

In this receive location configuration, I added two operations (“UpdateAccount”, “DeleteAccount”) and set the corresponding HTTP verb and URI template.

2012.11.12rest12

I could list as many service operations as I wanted here, and notice  that I had TWO parameters (“pid”, “aid”) in the URI template. I was glad to see that I could build up complex addresses with multiple parameters. Each parameter was then mapping to a property schema entry.

2012.11.12rest13

After saving the receive location configuration, I configured a quick FILE send port. I left this port enlisted (but not started) so that I could see what the message looked like as it traveled through BizTalk. On the send port, I had a choice of new filter criteria that were related to the new WCF-WebHttp adapter. Notice that I could filter messages based on inbound HTTP method, headers, and more.

2012.11.12rest14

For this particular example, I filtered on the BTS.Operation which is set based on whatever URL is invoked.

2012.11.12rest15

I returned to Fiddler and changed the URL, switched my HTTP method from POST to PUT and submitted the request.

2012.11.12rest16

I got an HTTP 200 code back, and within BizTalk, I could see a single suspended message that was waiting for my Send Port to start. Opening that message revealed all the interesting context properties that were available. Notice that the operation name that I mapped to a URL in the receive adapter is there, along with various HTTP header and verbs. Also see that my two URL parameters were successfully promoted into context.

2012.11.12rest17

 

Summary

That was a quick look at exposing REST endpoints. Hopefully that gives you a sense of the native aspect of this new capability. In the next post, I’ll show you how to consume REST services.

Author: Richard Seroter

Richard Seroter is Director of Developer Relations and Outbound Product Management at Google Cloud. 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 Director of Developer Relations and Outbound Product Management, Richard leads an organization of Google Cloud developer advocates, engineers, platform builders, and outbound product managers that help customers find success in their cloud journey. Richard maintains a regularly updated blog on topics of architecture and solution design and can be found on Twitter as @rseroter.

43 thoughts

  1. I got an error – Receive location for address “/GPS/Service1.svc” not found ,
    when entering the following url on my browser: http://localhost/gps/Service1.svc?wsdl

    I also received this error when submitting POST via Fiddler (http://localhost/gps/Service1.svc )

    Orchestration Datasmith.Samples.BizTalkRest1.MsgOrchestration
    Port: WcfReceivePort_gps/Service1
    receive Location Name: WcfService_gps/Service1
    URI: /gps/Service1.svc

    Mapping:

    In web.config, I noticed no entries for receiveLocationMappings – not sure if this is an issue.

  2. I fixed this, thanks.

    another issue.

    I installed Biztalk 2013 Beta on Windows 2008 R2. I also installed .Net Framework 4.5.

    My problem is that when i select WCF_Custom, the UDP Binding is not present in the drop-down combo box on the Bindings tab.

    Any suggestions on how to resolve this?

    1. Apparently, 32 bit & 64 bit machine.config needs to be updated, since Biztalk admin application is 32 bit, whereas, adapter is 64 bit.

      MS documentation doesn’t remind developer that both locations need to be updated, it usually just states update machine.config.

      MS should have a common\machine.config for configurations that both 32-bit & 64-bit rely on.

      1. Hey Larry

        I’m sorry, but it is the .net 4.5 machine.config files that need to be edited, I guess?
        Can you explain shortly what and where needs to be addes,

        Tnx!

  3. Great Article!, Can you please explain on what the SetUnitque ID Message Assignment shape does? Based on the screenshot it looks like the UserName property has been promoted but not ID property. How are you setting the ID Property? Please advise.

    1. I am trying to implement the Scenario 1 of this Article and i am getting the Routing Failure Report and the Message is getting suspended. When i see the error report the BTS.Operation have been promoted to have value of CreateAccount but the message Type is blank. Please advice on what could be the problem here.

      1. I am struggling a but to use the expression editor to create the ack message, and assign the generated GUID… any hints on how to do this? Thanks!

  4. Hi Mike, if I recall, the “ack” message is the same as the input message type, just with a populated ID. To generate the ID, I typically use “msg.Id = System.Guid.NewGuid().ToString();”

    1. Thanks for the reply Richard, the only message I have defined is “Account_Input” whose message type is the Account_XML schema as in your example. I do use this message as both the receive and send message of the orchestration. The problem I am having is with the expression in the message assignment shape inside the construct message shape. I am using “Account_Input.ID = System.Guid.NewGuid().ToString();”. The expression editor tells me: “identifier ID does not exist in Account_Input; are you missing an assembly reference?”. When I try to build the solution it tells me that 1) the expression is in error, 2) ‘Account_Input’: message has not been initialized in construct statement, 3) use of unconstructed message ‘Account_Input’. Is there any thing else I am doing wrong here? Thanks again for your help.

      1. I see. You’ll need another message of the same type, and the Construct shape is for that message. Then copy the first by doing Msg2=Msg1; Msg2.AccountId = System.Guid.NewGuid().ToString()

  5. Richard
    I am also getting same error as Mike but still confused in that Message Assignment shape. I am new in Biztalk. FYI, I created a schema as you showed in your post with same name.
    can you please explaine more in detail please. thank you onces again.

    1. Hi Ravi. So the Message Assignment shape is for instantiating new messages. You should have two messages, both of the same type. The first message is the one received by the orchestration, so it’s instantiated by default. The second — which has the generated ID in it — needs to be built before it can be sent as a response. To build it, you specify the 2nd message as the “message to build” for the Construct shape, and then in the Assignment shape, you can instantiate the second message by “copying” the first (Message2 = Message1;). Then you just set the value (and make sure that you’ve distinguished the schema field you want to set here) of the ID field (Message2.Id = ‘123’).

      1. Richard
        Thankyou for fast reply..
        As you mentioned I did make my ID field in Account schema as distinguisted field.
        first message i created as MsgAccInput and set Message type as schema
        second message i created as Message_1 and set message type as schema (with same schema which i selected for MsgAccInput)
        and as you mentioned I did the following in message assingment shape under construct message
        Message_1 = MsgAccInput;
        Message_1.ID = “123”;
        Error is: Identifier ‘ID’ does not exist in ‘Message_1’; are you missing an assembly reference?

        Thank you once again..

    2. Richard,
      when you using in Receive port. Url=”/Property/{pid}/Account” I am confused here what is property and what is Account I am guessing Property is name of PropertySchema and Account is rootnode name of Account_XML.xsd…
      is there any other configuration you doing in receive port..like in behavior for servicebehavior or endpoint behavior!!!

      1. Hi Ravi. In this post, remember that “Property” in the URL refers to the use case (sharing information about websites) and has nothing to do with property schemas. The “pid” parameter refers to which website property we’re referring to. The URL describes the resource, but the values I used don’t necessarily matter. We’re posting an XML payload to this URL, and THAT is what maps to the schema. The URL variables (like pid and aid) are thrown into the message context. That’s the only mapping from URL to message.

      2. Richard,
        do you mind to review my work of WCF-webhttp. I am getting error while consuming it.
        Error is
        Error consuming wCF service metadata. Message part missing element. Correct service description “http://tempuri.org/” message type =”Service1_operation1_inputmessage” part “Part” nad return the wizard.
        if you provide me your email I can send you a screen shot of my work. if that help you out to solve it. my id is raviraj00144@yahoo.com
        thank you once again

  6. I know this post is a bit dated, but does all of this still hold true for BizTalk 2013 R2? Any changes?
    also, is there anyway that you could share the project files (e.g. GitHub, or Dropbox/OneDrive)? It would help me (and probably others) immenselly, as there are implicit steps that happened (such as setting up the receive ports, etc.), which may be trivial but for newbies this is invaluable. Thanks!

  7. Great article.

    I am using BizTalk server 2013 R2. I have a BizTalk Orchestrations project which has 10 Orchestrations and all the 10 accepts 10 different JSON message types. When i publish using WCF-WebHttp for synchronous call, it creates one receive port and one receive location in Admin console. At this point i can only select one receive pipeline to convert JSON to XML and one send pipeline to convert XML to JSON. I would like to expose remaining 9 message types to outer world.
    1) Can i achieve this via creating 9 receive locations within the receive port with its 9 different send/receive pipelines of it own message types?
    2) How this will work with IIS?
    3) Is there any other solutions to achieve this?

    Thanks for your help in advance.

    1. Hmm, I would *think* you’d want to create a unique receive location/pipeline per request type, or, you’d need the smarts within the pipeline to discern each inbound message type.

  8. Hi Richard,

    I have an orchestration, which was using an HTTP receive location (BTSHTTPReceive.dll), and now want to configure it with WCF-WebHttp adapter (to utilize using behaviors).

    I have created a WCF-WebHttp receive location using the WCF Expose Wizard, and bound that receive location to my orchestration.

    My question is what should I fill in the BTSHttpUrlMappaing, mainly what is the url value should I assign? I just want to receive the request, let it process through the orchestration, and get back the processing result.

    Thanks in advance

  9. Hi Richard,

    I am exposing a REST-ful Service in Biztalk using WCF-WebHttp adapter. It is a GET service which accepts a parameter “userID”. So basically my service URL looks like this “http://localhost/CEMOneWayRest/Service1.svc/GetProjectDetails/{userID}”. The UserID is an integer which is passed as a parameter inside the REST service . In my Biztalk Solution , I have created a schema with userID element and promoted the property and have also created a variable mapping in my receive adapter. Since the GET service doesn’t contain a message context/message body, how can I activate an orchestration when the REST service is hit. ? And also I need to access the userID passed in the URL into my Orchestration.

    Kindly suggest.

    Thanks in advance…

    1. Hi Murli,
      I also have the same question. Did you resolve this problem. If yes, could you please provide the solution or source code. SO that I can resolve it.
      Thanks,
      EmailID:tuhinkanrar420@gmail.com

Leave a Reply to Barathan K Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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