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:
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.
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.”
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.
After choosing the new web service address, I located my new service in IIS and a new Receive Location in the BizTalk Engine.
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.
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.
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.
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.
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.
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.
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.
For this particular example, I filtered on the BTS.Operation which is set based on whatever URL is invoked.
I returned to Fiddler and changed the URL, switched my HTTP method from POST to PUT and submitted the request.
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.
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.
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.
btw, The following was used to create the Receive Port via the Biztalk WCF publishing wizard:
The following was used to create the Receive Port via the Biztalk WCF publishing wizard:
Can you browse the endpoint via IIS? Are you sure that the Receive Location is enabled?
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?
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.
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!
*added 🙂
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.
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.
The unique ID is just a random GUID that acts as the account ID on the returned message. Simply used System.Guid.NewGuid().ToString() to generate it.
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!
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();”
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.
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()
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.
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’).
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..
Hmm. That happens sometimes happens if the compiler can’t resolve the distinguished field name. Any chance your project has a reserved value in it (http://sandroaspbiztalkblog.wordpress.com/2012/02/28/identifier-retrycount-does-not-exist-in-myprojectnamespace-are-you-missing-an-assembly/)?
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!!!
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.
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
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!
Great article. Looking for the application or msi file. To understand better
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.
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.
Hi Richard,
Great Article, does it also support JSON format or is it only xml?
I believe that the latest version now does process JSON successfully.
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
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…
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