BizTalk 2016 – Consuming RESTful API Hosted on Azure API Management Service – GET Request
Part 1
Recently I was given the task (using JSON) to consume a RESTful API Hosted on Azure API Management Service, with https connection. Having no prior experience on how REST works and how to consume a JSON Hosted on Azure API Management Service, I started with my usual research on the web on what needs to be done. A few good blogs and articles later I realized it should be pretty simple and I should be able to do this within no time at all. After spending a couple of hours building the usual artifacts, and satisfied with the solution, I decided to test it… And there it was, the error…
Error
A message sent to adapter “WCF-WebHttp” on send port “SP.MasterData.GetSKU” with URI ” Error! Hyperlink reference not valid.” is suspended.
Error details: System.ServiceModel.CommunicationException: An error occurred while making the HTTP request to Error! Hyperlink reference not valid.. This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could also be caused by a mismatch of the security binding between the client and the server. —> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. —> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. —> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
RESTful API Hosted on Azure API Scenario Background
Problem Definition
- Consume the RESTful API Hosted on Azure API Management Service. (https, not http)
- The API request and response should to be JSON.
- The connection authentication is credential based, i.e. a username and a password.
- An Ocp-Apim-Subscription-Key is provided which helps the API Service identify the source.
Solution
The solution was designed to be very simple without having to write any custom code, building the least amount of artifacts, just as a POC for consuming a RESTful API Hosted on JSON
I wanted to
- Drop the XML request, derived from JSON request schema, to a file location,
- Have a send port subscribe to it and call the REST API
- Receive the response back from the API, convert it back to XML
- Have a send port subscribe to the response and send it to a file location.
In order to send the request, receive a response, and work with it in BizTalk, I needed the XML schema equivalent of the JSON request and response.
Defining the JSON Request-Response schemas
- I got the sample JSON request and response of the GET method, that I intended to call, and stored it their individual files.
- For each of the request and response messages, added a New Item in my BizTalk project and chose JSON Schema Wizard
3. In the Instance file option, chose the file that had the request/response .
4. Gave it an appropriate Root node name and Target namespace .
I usually like my Request-Response in the same schema, hence once I had the schemas for Request and Response, I combined it in one schema for ease and deleted the one I did not need.
Unfortunately, the JSON Schema Wizard is not as flexible as the Flat File Schema Wizard, and more often than not you will have to adjust the schema, i.e. the data type, data structure type etc.
Now, the Request was in JSON and I had the send port subscribing to the XML version of the Request schema, in order to convert it from XML to JSON, receive a response and convert it back to XML, I needed pipelines.
Defining the Send pipeline – to send JSON request
- Added a new send pipeline in the BizTalk project,
a. XML assembler in the Assemble stage
b. JSON encoder in the Encode stage.
i. Set the RemoveOuterEnvelope property to True.
Defining the Receive pipeline – to receive JSON response
- Added a new receive pipeline in the BizTalk project.
a. JSON decoder in the Decode stage
i. AddMessageBodyForEmptyMesage: False
ii. RootNode: <Root Node name of the Request schema defined above>
iii. RootNodeNamespace: <Namespace of the Root Node of the Request schema defined above>
b. XML disassembler in the disassemble stage
Since GET method had parameters which are passed as a query string, hence I needed a property schema to promote the property of the incoming message and use it on the send port while defining and mapping parameters (we will see this ahead).
Defining a property schema and promoting
- Added a new property schema to the project.
- Added a new Node- BatchID – This is the node that will hold the Batch Id field defined in the request schema.
- In the request schema, defined above, I promoted the BatchID field and mapped it to BatchID field in the property schema
After deploying all the above artifacts, this is how I configured the application.
Configuring the BizTalk Application
- Created a Receive location with the XML Receive pipeline, which takes the XML request as the input.
- Created a Solicit-Response Send Port that subscribes to the messages from the Receive Port defined for the above Receive Location.
- Configured the send port to use the two pipelines created above .
- For the send port, Transport Type was selected as WCF-Web-Http
- For configuring the Transport type
a. Entered the URI for the API service in the Address (URI).
b. HTTP Method and URL Mapping:
<BtsHttpUrlMapping>
<Operation Method=”GET” Url=”/<method>?batchid={BatchID}” />
</BtsHttpUrlMapping>
c. In Variable Mapping –> Edit, entered the Property Name and Property Namespace against BATCHID (this is property that was promoted from the Response schema). The property name and the namespace here will be from the Property schema defined above.
d. In Security tab, I defined the
i. Security Mode: Transport
ii. Transport client credential Type: Basic
iii. Entered the API credentials for authentication in the section User name credentials.
e. In the Messages tab,
i. Outbound HTTP Headers:
Ocp-Apim-Subscription-Key: <key provided to use API>
Content-Type: application/json
ii. Outbound Message, Suppress Body for Verbs: GET
f. Created another send port which subscribed to the response messages.
After configuring the application and dropping the test XML request at the file location the file was successfully converted to JSON, and the request was sent to the RESTful API configured at the Send Port. I expected it to return the response back and see it in the file location configured on the send port subscribing to the response. However, it was not over yet, and I still had the below error to solve in order to see a successful response.
Error
A message sent to adapter “WCF-WebHttp” on send port “SP.MasterData.GetSKU” with URI ” Error! Hyperlink reference not valid.” is suspended.
Error details: System.ServiceModel.CommunicationException: An error occurred while making the HTTP request to Error! Hyperlink reference not valid.. This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could also be caused by a mismatch of the security binding between the client and the server. —> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. —> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. —> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host.
The above solution to consume a RESTful API Hosted on Azure API should work perfectly, in a scenario similar to mine, if you have everything in place or if you are not doing an https call. However, in some cases, like mine, you might have to solve the above error in order to see the response.
Upcoming Part 2 of the RESTful API Hosted on Azure API
I want to keep this post limited to consume a RESTful API Hosted on Azure API. The solution to the above error will be in PART 2 of this post. It will consist of the solution to the above error and the POST call to the RESTful API.
We encourage you to leave your comments below and check our other posts.
You can also contact us for a free consultation.