A few weeks ago, I posted about AL support for REST Web Services. And at the end I promised to convert the previous posted web service examples to AL code. The first three are now available on GitHub. Feel free to clone, fork and play with it.
The code consists of a set of base objects and a set of objects per web service example. The base objects are reused by all web service examples. In the base objects there are a number of objects:
- Table RESTWebServiceArguments
- Codeunit RESTWebServiceCode
- Codeunit JSONMethods
- Pageextension BusinessManagerRoleCenter
The RESTWebServiceArguments table is used to implement the Argument Table pattern. With this pattern, we have less dependency between functions and a change in the parameters doesn’t have a ripple effect.
The table holds fields like REST method, URL, UserName and Password. And it has a Blob field to store the complex type HttpContent. Besides the fields, there are functions to set and get HttpContent for the request and the response.
The HttpContent for the request is saved into a global variable, while the resulting HttpContent (from the response) is stored into the Blob field. The reason is that the response content cannot be hold into memory with a global variable. This is not a AL restriction, it also appears in .Net. I will spare you the details, I have tried out different ways before I came up with this one.
This codeunit is at the heart of the web services. It accepts the argument table and builds up a complete HttpRequestMessage to be sent to the web service.
When you compare this to the first AL web service example, you will see a big difference. In that example the code to call a web service was fairly straightforward: HttpClient.Get(URL,HttpResponseMessage). The HttpClient as of course also functions for Post, Delete, etc.
In this codeunit we use the method HttpClient.Send(HttpRequestMessage,HttpResponseMessage). The difference is that the HttpRequestMessage is completely prepared with all necessary parameters, like URL, HTTP method, headers (e.g. credentials) and content (for post methods).
After the Send method, we get back a HttpResponseMessage that is stored into the parameters table.
This codeunit has two functions to read a Json value from a JsonObject. It is just some code to avoid having to write these lines of code over and over again.
Because we currently cannot add new items to the search result (e.g. Menusuite, although Microsoft is apparently thinking of a different solution according to some GitHub issues) I decided to put the web service examples to the Business Manager Role Center.
Web Service Verify E-mail Address
This web service was introducted in this article. The AL code is pretty simple, using the base objects of course. Have a look at codeunit VerifyEmailAddress to see how it works. The functionality is applied to the E-mail field of the Contact table using a Table extension object.
Web Service Generate Barcode Images
This web service was introduced in this article. I have redesigned the objects for better readability. The most interesting part is probably in function SaveResult in codeunit GenerateBarcode, where the resulting image is stored into the Media field. The HttpContent object contains binary data instead of text, so we use an InStream object to read the data of the response.
Web Service Sending SMS with BulkSMS
This web sevice was introduced in this article. I have again redesigned the objects for better readability. The code is pretty much the same as before. There was an important difference, though.
The request content for the BulkSMS send sms web service must be called by using the POST method. To post something over HTTP, you use a request content. However, with AL code it turned to be a little bit tricky.
In the version for C/AL code I used a StringContent object to create content with the correct media type. What am I talkin about? Look at this C/AL code snippet:
The media type is ‘application/x-www-form-urlencoded’. This is a specific type of posting data over HTTP. Think of it as a form that you fill out on an internet page and when you post it the data is put into a large querystring, like field1=value&field2=value, etc. This is not the default value for the media type. The default is ‘multipart/form-data’.
Why is this important? Well, the AL object HttpContent uses ‘multipart/form-data’ as default setting without an option to change it when you set the content. That resulted in error messages because the web service expected a different content type.
After some test, I found out that it is possible to change the content type header of the HttpContent object. By first removing the existing content type header and then add the correct one. You can see that in this code in the InitArguments function of the BulkSMSSendMessage codeunit.
The code was not created in a breeze. Although there are not many objects in it, typing it all in with VS Code is somewhat time consuming. Time will tell if this is going to affect the planning of development time when we fully switch to AL code development.
You may have seen my previous post about Base64 encoding. Although I have this code, I decided to not use it and stay with the Base64 functions in the TempBlob table (used in codeunit RESTWebServiceCode). The reason is that the functions in the TempBlob table are faster compared to the AL code. Another reason for Microsoft to embed as much .Net functionality in AL code as possible. We have seen XML support in the July update and for the August update we expect String functions.
The code is only compatible with the July update, and hopefully with higher versions. No guarantees though, it is all beta software and things can change or break in next updates.