With this first part in the series on web services examples demonstrated at Directions and NAV Techdays, I want to introduce a pattern that can be reused to call any REST web service.
Why specifically REST web services and nothing about SOAP? That’s because I searched for really useful web service examples and soon found out that almost any web service support REST. To be honest, I couldn’t find any (useful) web service that did not support REST.
To read more about the difference between SOAP and REST, I recommend you to read this article, back from 2010: http://spf13.com/post/soap-vs-rest
What is REST?
REST stands for ‘Representational State Transfer’ and it is an architectural pattern for creating an API. It is based on the HTTP communication protocol, which is the base protocol of the internet.
HTTP is basically a request and response mechanism. The client sends a request to an endpoint and the endpoint answers with a response. An example can be a web browser (the client) that calls a web server (the endpoint). The web server responses with an HTML page.
There are some key details with HTTP that you should know about. All these will come back in the pattern to call a REST web service.
Resource – REST uses an address, or URL, that defines the API. In fact, the URL represents the resource.
Request Verb – The verb describes what you want to do with the resource. A browser uses the GET verb to tell the endpoint that it wants to get data. Other verbs are POST, PUT and DELETE.
Request Headers – In the header you can sent additional instructions together with the request. Most commonly the request headers are used for authorization or to define the type of response that you expect.
Request Body – This is data that is sent with the request. This can be used together with the POST verb. Think of a web form that is sent to the server when you click the submit button.
Response Body –The response body is the main body of the response. If a web browser requests a resource, using the GET verb, the response body might be a full HTML page. If the resource was an API, the response body could contain a JSON or XML document. Or a base64 encoded byte array that holds an image. Or…
Response Status Code – Together with the response, you receive a status that gives the client details on the status of the request. For example, status 200 means that the request was successful.
To put the above key details together in two sentences that generally describes a call to a REST web service:
You call a Resource using a Request Verb, optionally accompanied by a Request Header and a Request Body. The response contains a Response Status Code which describes the status of the call and a Request Body that contains the requested data.
Starting with NAV 2015 there are a couple of Codeunits that handle web service calls using .Net class System.Net.HttpWebRequest. Take a look at Codeunits 1290, 1297 and 1299. There is a lot of code there, and you really need to find your way through it. Of course, you can use these Codeunits to call any web service.
However, there is an easier way to call web services: System.Net.Http.HttpClient (in System.Net.Http.dll). This class is designed as an easy to use alternative for the HttpWebRequest. It can be used for the majority of web service integrations. Only when you need more low level control over the request and response, you should use HttpWebRequest, otherwise HttpClient makes your life much easier. More information can be found here and here. The HttpClient is available with .Net Framework 4.5 and can be used with Dynamics NAV 2015 and higher.
The HttpClient is very easy to use. There is a method for each of the request verbs. For example, HttpClient.GetAsync(uri) calls the uri using the GET verb and returns the response message. As you can see in the name, the method is asynchronous. That is not supported by C/AL. However, if we add .Result to the end, like HttpClient.GetAsync(uri).Result, execution will wait until the response is received before it continues.
Allright, that’s enough theory, let’s show the code.
CallRESTWebService(BaseUrl : Text;Method : Text;RestMethod : Text;VAR HttpContent : DotNet "System.Net.Http.HttpContent";VAR HttpResponseMessage : DotNet "System.Net.Http.HttpResponseMessage")
HttpClient := HttpClient.HttpClient();
HttpClient.BaseAddress := Uri.Uri(BaseUrl);
CASE RestMethod OF
HttpResponseMessage := HttpClient.GetAsync(Method).Result;
HttpResponseMessage := HttpClient.PostAsync(Method,HttpContent).Result;
HttpResponseMessage := HttpClient.PutAsync(Method,HttpContent).Result;
HttpResponseMessage := HttpClient.DeleteAsync(Method).Result;
HttpResponseMessage.EnsureSuccessStatusCode(); // Throws an error when no success
Explanation of the parameters
BaseUrl – the first part of the url that is being called, e.g.: http://www.webserviceaddress.com/
Method – the resource on the web service, in other words, the second part of the url, e.g. somecoolapi/parameter?option=value
RestMethod – one of the request verbs, either GET, POST, PUT or DELETE
HttpContent – the content to be sent with the POST or PUT command
HttpResponseMessage – the response message containing the status code and the response body. This parameter is ByVar because the calling code needs to handle the specific response itself. That’s not part of the generic pattern.
Remarks about this pattern
Request headers are not used here. That will be added as part of the more advanced demo in part 7.
The call to EnsureSuccessStatusCode method on the HttpResponseMessage throws an error if the IsSuccessStatusCode property on the response message is false. It is not mandatory to use this. But if you skip it, make sure to test the IsSuccessStatusCode on the HttpResponseMessage yourself and handle any error situation.
In the next part we are going to use this pattern for the first web service example: verify e-mail address.
See you soon. Stay tuned!
Pingback: Web Services Examples Part 1 – The Basic Pattern - Microsoft Dynamics NAV Thoughts - Dynamics User Group
Pingback: Web Services Example | Arul Consulting Group
Thanks for a wonderfull session during nav tech days.. I saw the video few days back and rly enjoyed learning web services.. Thanks again 🙂
NAV 2016, Error occur when save the codeunit as explained above
The function call was ambiguous. No matching method was found.
Pingback: NAV Integration with Trello – Marcellus Nav Blog
I am trying to get an access token from Azure AD for an web app using NAV2017 webclient/RTC registered as an webapp in azure. I have tried to follow your example and lots of other blogs separately but have failed everytime and whenever I make a GET request the response comes with a sign in page, even though I have tried to pass credentials but it didn’t work and everytime the response is same, now how can I get the authorization code for a GET without being redirected to signin page and then use that code to make POST request to my tenant to get the access token for the webapp from the webclient.
Chandra Prakash Soni
To get an authorization token without redirect to a login page, you have to get admin consent. This can be done on Azure AD or by requesting specific admin consent the first time. https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#using-the-admin-consent-endpoint
Pingback: Calling external web services From Dynamics NAV/Business Central | PA
Pingback: HttpClient.GetAsync(method).Result | PA