Dynamics 365 Dynamics NAV 2017

Consume OpenWeather REST Api in Dynamics Nav

Representational state transfer (REST) or RESTful Web services are one way of providing interoperability between computer systems on the Internet. REST-compliant Web services allow requesting systems to access and manipulate textual representations of Web resources using a uniform and predefined set of stateless operations.

Wikipedia- https://en.wikipedia.org/wiki/Representational_state_transfer

 

Consuming rest api in Navision is done with the help of some inbuilt Dotnet add-in DLLs.

Openweather provides a standard and easy to set up APIs that we are going to consume in Nav. Just visit http://openweathermap.org/api , register and then create your unique api key which gives you access to consume data from them based on the parameters you pass.

The tricky part is to save the result from a json deserializer.

For more info of Api Calls of Openweather Visit http://openweathermap.org/current

 

OBJECTIVE

Create a Codeunit to consume Openweather API in Nav

Steps to consume this API in Nav.

  1. Create a new codeunit in your range

 

  1. Create a new function

You will need some local variables defined as well

Syntax

Url := apiurl;

HttpWebRequestMgt.Initialize(Url);

HttpWebRequestMgt.DisableUI;

HttpWebRequestMgt.SetMethod('GET');

HttpWebRequestMgt.SetReturnType('application/json');



TempBlob.INIT;

TempBlob.Blob.CREATEINSTREAM(Instr);



IF HttpWebRequestMgt.GetResponse(Instr,HttpStatusCode,ResponseHeaders)

THEN BEGIN

  IF HttpStatusCode.ToString = HttpStatusCode.OK.ToString

    THEN BEGIN

      Json := TempBlob.ReadAsText('',TEXTENCODING::UTF8);

      JObject := JObject.Parse(Json);

      temp := JObject.GetValue('main').ToString;

    

      MESSAGE(temp);



    END ELSE

      MESSAGE('status code not ok');

END ELSE

  MESSAGE('no response from api');

 

I have also defined a text constant with hardcoded Api url for testing purpose.

http://api.openweathermap.org/data/2.5/weather?q=london&appid=<yourappid>

This url structure fetches the weather data for London from Openweather Servers.

For more info of Api Calls of Openweather Visit http://openweathermap.org/current

Output of the above code

The output is in a serialized format. We need to deserialize it. This can be done using two approaches.

Approach 1

You can either treat the output as string and write CAL’s string commands by using something like below.

 

temp:=(SELECTSTR(3,temp));

MESSAGE(temp);

pos:= STRPOS(temp,':');

temp:=DELSTR(temp,1,pos);

MESSAGE('Humidity is '+temp);

 

Output

Approach 2

We can use control add-ins to deserialize the output from Api. This can be done using a opensource library that can be found here. Luckily Microsoft has already included this atleast in  Nav 2017.  All we need to do is copy this dll from C:\Program Files (x86)\Microsoft Dynamics NAV\100\RoleTailored Client and into C:\Program Files (x86)\Microsoft Dynamics NAV\100\RoleTailored Client\Add-ins.

 

Next when we deserialize the JSON using this library we need to be able to save the deserialized outputs. This can be done using a very simple custom Addin. Adapt the process from https://blogs.msdn.microsoft.com/nav/2010/07/09/let-nav-speak-with-a-simple-and-useful-client-add-in/ and use the following code.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;





public class Rootobject

{

    public Coord coord { get; set; }

    public Weather[] weather { get; set; }

    public string _base { get; set; }

    public Main main { get; set; }

    public int visibility { get; set; }

    public Wind wind { get; set; }

    public Clouds clouds { get; set; }

    public int dt { get; set; }

    public Sys sys { get; set; }

    public int id { get; set; }

    public string name { get; set; }

    public int cod { get; set; }

}



public class Coord

{

    public float lon { get; set; }

    public float lat { get; set; }

}



public class Main

{

    public float temp { get; set; }

    public int pressure { get; set; }

    public int humidity { get; set; }

    public float temp_min { get; set; }

    public float temp_max { get; set; }

}



public class Wind

{

    public float speed { get; set; }

    public int deg { get; set; }

}



public class Clouds

{

    public int all { get; set; }

}



public class Sys

{

    public int type { get; set; }

    public int id { get; set; }

    public float message { get; set; }

    public string country { get; set; }

    public int sunrise { get; set; }

    public int sunset { get; set; }

}



public class Weather

{

    public int id { get; set; }

    public string main { get; set; }

    public string description { get; set; }

    public string icon { get; set; }

}

 

This code can be automatically generated by Visual Studio according to the json you want to use. All you need to do is copy the output of the json from browser and use Paste Special>Paste Json as Classes option under Edit in Visual Studio.

 

Compile the project following the msdn blog and paste the Dll in Control Addins folder of Nav

C:\Program Files (x86)\Microsoft Dynamics NAV\100\RoleTailored Client\Add-ins

 

Now we can modify our CAL code in the codeunit

You will need to declare the following local and global variables.

Local

Global

JsonConvert and JObject are using Newtonsoft library dotnet data type. The Add-in we created is called Result.

 

Syntax

Url := apiurl+CityName+apikey+'&units='+Units;

HttpWebRequestMgt.Initialize(Url);

HttpWebRequestMgt.DisableUI;

HttpWebRequestMgt.SetMethod('GET');

HttpWebRequestMgt.SetReturnType('application/json');



TempBlob.INIT;

TempBlob.Blob.CREATEINSTREAM(Instr);



IF HttpWebRequestMgt.GetResponse(Instr,HttpStatusCode,ResponseHeaders)

THEN BEGIN

  IF HttpStatusCode.ToString = HttpStatusCode.OK.ToString

    THEN BEGIN

      Json := TempBlob.ReadAsText('',TEXTENCODING::UTF8);

      JObject := JObject.Parse(Json);

      temp := JObject.GetValue('main').ToString;

      Result := Result.Main;

      Result := JsonConvert.DeserializeObject(temp,GETDOTNETTYPE(Result));

      //MESSAGE(FORMAT(Result.temp));

     CASE Param OF

          'temp':

          EXIT(FORMAT(Result.temp));

          'temp_min':

          EXIT(FORMAT(Result.temp_min));

          'temp_max':

          EXIT(FORMAT(Result.temp_max));

          'pressure':

          EXIT(FORMAT(Result.pressure));

          'humidity':

          EXIT(FORMAT(Result.humidity));

       END

    END ELSE

      MESSAGE('status code not ok');

END ELSE

  MESSAGE('no response from api');

 

This function can then be called and will give the result as we pass the paramters

 

Please Note This is only a sample code is not production quality

 

2 comments

Leave a Reply

Your email address will not be published. Required fields are marked *