Introduction
There might be situations when an external app needs to use Business Central web services but you don’t want it to access directly the BC web service. Instead we can have something like a “middle tier” app which does the following:
– receives requests from external world,
– sends requests to BC
– receives responses from BC
– sends responses back to external app.
Some advantages of this are:
– the “middle tier” could handle BC authentication.
– the “middle tier” could make some transformation of the request data sent by the external app and then send request to BC in a different way.
– the “middle tier” could make some transformation of the BC response data before it sends it back to the external app which initiated the request.
Context of the example
If you are a web developer the middle tier service can be easily done and published using different web development frameworks. But if you are a NAV / BC Developer and you don’t have a web developer colleague who can help with that, you can find the following solution interesting.
Please note that the example is based on the BC APIs v2.0
But, depending on your use case scenario, it can be adjusted to be used with any BC web services (SOAP, OData V3 or V4).
Creating the “middle tier” for BC Web Services using an Azure Function
Let’s see now how we can create our working example using an Azure Function.
–> After logging into the Azure Portal, we need to create a function using the “HTTP trigger template”.
–> Add the below code in the Azure portal development console (or you can create Visual Studio project and import in Azure portal):
#r "Newtonsoft.Json" using System.Net; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using Newtonsoft.Json.Linq; public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log) { string body = await req.Content.ReadAsStringAsync(); JObject RootObj = JObject.Parse(body); string httpMethod = (string)RootObj["httpMethod"]; JObject requestBody = (JObject)RootObj.SelectToken("requestBody"); var httpClient = CreateClient(); string URL = httpClient.BaseAddress + (string)RootObj["bcEndpoint"]; var requestContent = new StringContent(JsonConvert.SerializeObject(requestBody), System.Text.Encoding.UTF8, "application/json" ); HttpResponseMessage response = new HttpResponseMessage(); switch (httpMethod) { case "POST": response = await httpClient.PostAsync(URL, requestContent).ConfigureAwait(false); break; case "GET": response = await httpClient.GetAsync(URL).ConfigureAwait(false); break; } string respText = await response.Content.ReadAsStringAsync(); return new HttpResponseMessage( HttpStatusCode.OK ) {Content = new StringContent(respText, System.Text.Encoding.UTF8, "application/json" )}; } private static HttpClient CreateClient() { var httpClient = new HttpClient { BaseAddress = new Uri(Environment.GetEnvironmentVariable("BCBaseURL")) }; httpClient.DefaultRequestHeaders.Accept.Clear(); string _navUsername = Environment.GetEnvironmentVariable("BCUserName"); string _navPassword = Environment.GetEnvironmentVariable("BCPassword"); string authStr = string.Format("{0}:{1}", _navUsername, _navPassword); var byteArray = Encoding.ASCII.GetBytes(authStr); httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray)); return httpClient; }
–> Notice that in the above example the BC authentication is handled by the Azure function using environment variables:
Short Explanation about what the above Azure Function does
When it receives a request, it will try to deserialize the Request message string into a JSon Object (it expects JSon as body).
Then it reads from the JSon Object :
– value of field “httpMethod” which is used later to decide what type of request it sends to BC (GET, POST etc)
– value of field “bcEndpoint” which is used later to create the complete URL if the request it send to BC
– the body of the request to send to BC from field “requestBody”.
Considering the above parameters, the Azure function sends request to BC (using credentials defined as explained above- environment variables) and receives a Response from BC.
In the end, it sends back the Response to whom initiated the request.
Usage Examples
Let’s now see 2 examples of how we can send API requests from Postman to BC through the Azure Function “middle tier”.
I just implemented “GET” and “POST” methods in this function for now because it is just an example, but a real life solution would support also “PATCH”, “PUT”, “DELETE”.
–> Example of retrieving data about existing customers by sending a “GET” request:
–> Example of creating a new customer by sending a “POST” Request:
I hope you find this interesting.