web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Answered

How to display the response of a REST webservice in a readable way.

(0) ShareShare
ReportReport
Posted on by 50

Hello, 

I consume a webservice REST from a supplier to track the shipments. 

In AX I use this code : 

static void AccessingAPIv4(Args _args)
{
    str                             url;
    str                             method;
    str                             header;
    System.Net.HttpWebRequest       httpRequest;
    System.Net.HttpWebResponse      httpResponse;
    System.Net.WebHeaderCollection  headers;
    CLRObject                       clro;

    int batchSize = 1024;
    System.IO.Stream receiveStream;
    System.IO.StreamReader readStream;
    System.Text.Encoding encode;
    System.Char[] read;
    System.Text.StringBuilder sb;
    System.String readString;
    str contentEncoding;

    int countRead;

    ;

    url = "https://api.dachser.com/rest/v2/shipmenthistory?tracking-number=3616047827517440";
    method = "GET";

    try
    {
        clro         = System.Net.WebRequest::Create(url);
        httpRequest  = clro;

        headers = new System.Net.WebHeaderCollection();
        headers.Add("X-IBM-Client-Id", "77079f46c44fd809905968e00edc7eec");
        headers.Add("Accept-Language", "fr");

        httpRequest.set_Headers(headers);
        httpRequest.set_Method(method);
        httpRequest.set_ContentType("application/json");

        httpResponse = httpRequest.GetResponse();

        if (httpResponse)
        {
            receiveStream = httpResponse.GetResponseStream();
            contentEncoding = httpResponse.get_ContentEncoding();

            if (contentEncoding)
            {
                encode = System.Text.Encoding::GetEncoding(contentEncoding);
            }
            else
            {
                encode = new System.Text.UTF8Encoding();
            }

            readStream = new System.IO.StreamReader(receiveStream, encode);
            read = new System.Char[batchSize]();

            countRead = readStream.Read(read, 0, batchSize);

            sb = new System.Text.StringBuilder();
            while (countRead > 0)
            {
                readString = new System.String(read, 0, countRead);
                sb.Append(readString);
                countRead = readStream.Read(read, 0, batchSize);
            }

            readStream.Close();

            info(sb.ToString());
        }
    }
    catch(Exception::CLRError)
    {
        throw error(AifUtil::getClrErrorMessage());
    }

}

But the result in json is unreadable for a user : 

2625.2022_2D00_01_2D00_26_5F00_08_2D00_41_2D00_43.png

In XML : 

6710.2022_2D00_01_2D00_26_5F00_08_2D00_46_2D00_27.png

I would like to display a clear text. For example : 

ID : xxxxxxx

ShipmentDate : 2022-01-25

          Forwarder:

                    PartnerGLN : 4022128000003

                    Name : DACHSER SE Logistikzentrum Allgäu

          AddressInformation:

                    City: Memmingen

                    PostalCode : 87700

                    CountryCode : DE

          ShipmentWeight:

                    Weight : 811.59

                    Unit : kg

PortOfDeparture: CGC

PortOfDestination : MUC

Consignor:

          id:57335219

          partnerGLN : 5607427157528

          names : Sams c/o Taschenbier

          AddressInformation : 

                    Streets : Boulevard de Parc 12

                    City : Coupvray

                    postalCode: 77700

                    CountryCode : FR

.....

....

in XML on the supplier's API I get this information maybe it is clearer for you . 

{
    "shipments": [
        {
            "id": "A8653470034371833856",
            "shipmentDate": "2022-01-24",
            "forwarder": {
                "id": "6",
                "partnerGLN": "4022128000003",
                "names": [
                    "DACHSER SE Logistikzentrum Allgäu"
                ],
                "addressInformation": {
                    "city": "Memmingen",
                    "postalCode": "87700",
                    "countryCode": "DE"
                }
            },
            "shipmentWeight": {
                "weight": 811.59,
                "unit": "kg"
            },
            "portOfDeparture": "CGC",
            "portOfDestination": "MUC",
            "consignor": {
                "id": "84065035",
                "partnerGLN": "1774679107268",
                "names": [
                    "Daisy Duck"
                ],
                "addressInformation": {
                    "streets": [
                        "Boulevard de Parc 12"
                    ],
                    "city": "Coupvray",
                    "postalCode": "77700",
                    "countryCode": "FR"
                }
            },
            "consignee": {
                "id": "57335219",
                "partnerGLN": "5607427157528",
                "names": [
                    "Sams c/o Taschenbier"
                ],
                "addressInformation": {
                    "streets": [
                        "Bavariafilmpl. 7"
                    ],
                    "city": "Grünwald",
                    "postalCode": "82031",
                    "countryCode": "DE"
                }
            },
            "references": [
                {
                    "code": "003",
                    "value": "bmHTYBiz6r"
                },
                {
                    "code": "007",
                    "value": "8zW1V6Qulv"
                },
                {
                    "code": "HAW",
                    "value": "nYR45812933"
                }
            ],
            "status": [
                {
                    "statusSequence": 1,
                    "id": "12090048571",
                    "statusDate": "2022-01-24T04:31:00",
                    "eventSetter": {
                        "id": "6",
                        "partnerGLN": "4022128000003",
                        "names": [
                            "DACHSER SE Logistikzentrum Allgäu"
                        ],
                        "addressInformation": {
                            "city": "Memmingen",
                            "postalCode": "87700",
                            "countryCode": "DE"
                        }
                    },
                    "event": {
                        "code": "Z",
                        "extendedCode": "",
                        "description": "Livré conforme"
                    },
                    "signorOfTheProofOfDelivery": "POTTER"
                },
                {
                    "statusSequence": 2,
                    "id": "39703452818",
                    "statusDate": "2022-01-23T08:19:00",
                    "eventSetter": {
                        "id": "250",
                        "partnerGLN": "4046823000007",
                        "names": [
                            "DACHSER Denmark A/S Logistics Centre Copenhagen"
                        ],
                        "addressInformation": {
                            "city": "Hvidovre",
                            "postalCode": "2650",
                            "countryCode": "DK"
                        }
                    },
                    "event": {
                        "code": "A",
                        "extendedCode": "",
                        "description": "Expédié vers le terminal"
                    }
                },
                {
                    "statusSequence": 3,
                    "id": "57954173029",
                    "statusDate": "2022-01-21T19:29:00",
                    "eventSetter": {
                        "id": "60",
                        "partnerGLN": "5990034733003",
                        "names": [
                            "LIEGL & DACHSER KFT."
                        ],
                        "addressInformation": {
                            "city": "Pilisvörösvár",
                            "postalCode": "2085",
                            "countryCode": "HU"
                        }
                    },
                    "event": {
                        "code": "E",
                        "extendedCode": "",
                        "description": "Arrivé au terminal"
                    }
                }
            ]
        }
    ]
}

How to manage formatting?

Thanks a lot for your help. 

I have the same question (0)
  • Martin Dráb Profile Picture
    237,965 Most Valuable Professional on at

    Showing a web service response directly to users is very unusual. Why exactly do you want to do it? These messages are for communication between systems - your system wants to do something, it requests data from another system and then do something with it.

    Are you sure that the only action is displaying data to users?

    Are you sure that you want to display everything (e.g. id A8653470034371833856)?

    Do you consider correct that you would display datetime values like 2022-01-24T04:31:00, instead of using user-preferred date/time format and timezone?

    Don't you want to validate the data and allow features like "Show details"?

    The normal approach for displaying data to users is using forms. I believe that you should parse the JSON string, put data to tables (either regular ones or temporary), validate it and then show to users in a form.

  • mimi51340 Profile Picture
    50 on at

    Thank you for your reply. You are right. Some information are not necessary and it is better to format the result using user-preferred date/time format and timezone for example.

    The aim is to consult the delivery notes for an order in AX and to get the shipment tracking from the web service.

    It is possible to use form, but as you said, how to parse the json string to put data in a table ?

    Thnaks.

  • Martin Dráb Profile Picture
    237,965 Most Valuable Professional on at

    If I was, I would create a C# class library. I would generate C# classes from JSON (with Edit > Paste Special > Paste JSON as Classes) and the used Newtonsoft.Json library to deserialize the JSON string to instance of these classes.

    Then I would add a reference to this C# libary and call it from X++ (via CLR Interop). Mapping properties of classes to table fields is then very easy.

    Of course, there are other JSON-related libraries as well. In the worst case, you can write your own JSON parser.

  • mimi51340 Profile Picture
    50 on at

    How can I create a c# classes from JSON ? I do not understand sorry...

  • Martin Dráb Profile Picture
    237,965 Most Valuable Professional on at

    As I said, this can be done with Edit > Paste Special > Paste JSON as Classes in Visual Studio. If you want more details, simply put these keywords to a web search engine. You'll find pages like this: How To Paste JSON As Classes Or XML As Classes in Visual Studio.

  • mimi51340 Profile Picture
    50 on at

    Hello,

    So I created a library classes in Visual Studio like :

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace JSONLibrary
    {
    
        public class Rootobject
        {
            public Shipment[] shipments { get; set; }
        }
    
        public class Shipment
        {
            public Shipmentdate shipmentDate { get; set; }
            public Shipmentweight shipmentWeight { get; set; }
            public string forwarderConsignmentNumber { get; set; }
            public string portOfDeparture { get; set; }
            public string portOfDestination { get; set; }
            public Consignor consignor { get; set; }
            public Consignee consignee { get; set; }
            public Reference[] references { get; set; }
            public Status[] statuses { get; set; }
            public string[] ssccs { get; set; }
        }
    
        public class Shipmentdate
        {
            public string date { get; set; }
        }
    
        public class Shipmentweight
        {
            public string weight { get; set; }
            public string unit { get; set; }
        }
    
        public class Consignor
        {
            public Partnerinformation partnerInformation { get; set; }
        }
    
        public class Partnerinformation
        {
            public string partnerName { get; set; }
            public string partnerGLN { get; set; }
            public Addressinformation addressInformation { get; set; }
        }
    
        public class Addressinformation
        {
            public string street { get; set; }
            public string postalCode { get; set; }
            public string countryCode { get; set; }
            public string city { get; set; }
        }
    
        public class Consignee
        {
            public Partnerinformation1 partnerInformation { get; set; }
        }
    
        public class Partnerinformation1
        {
            public string partnerName { get; set; }
            public string partnerGLN { get; set; }
            public Addressinformation1 addressInformation { get; set; }
        }
    
        public class Addressinformation1
        {
            public string street { get; set; }
            public string city { get; set; }
            public string postalCode { get; set; }
            public string countryCode { get; set; }
        }
    
        public class Reference
        {
            public string code { get; set; }
            public string referenceNo { get; set; }
        }
    
        public class Status
        {
            public string statusSequence { get; set; }
            public string statusNumber { get; set; }
            public Statusdate statusDate { get; set; }
            public Eventsetter eventSetter { get; set; }
            public Event _event { get; set; }
        }
    
        public class Statusdate
        {
            public string date { get; set; }
            public string time { get; set; }
        }
    
        public class Eventsetter
        {
            public Partnerinformation2 partnerInformation { get; set; }
        }
    
        public class Partnerinformation2
        {
            public string partnerGLN { get; set; }
            public string partnerName { get; set; }
            public Addressinformation2 addressInformation { get; set; }
        }
    
        public class Addressinformation2
        {
            public string city { get; set; }
            public string postalCode { get; set; }
            public string countryCode { get; set; }
        }
    
        public class Event
        {
            public string code { get; set; }
            public string extendedCode { get; set; }
            public string description { get; set; }
        }
    
    }
    

    I added the library in AX as Reference. 

    I created a new class in AX. I think I need to declare all objects ? 

    2022_2D00_01_2D00_27_5F00_11_2D00_42_2D00_40.png

    And now how to exploit the result of the web service to send it in a table from this method ? 

    static void AccessingAPIv4(Args _args)
    {
        str                             url;
        str                             method;
        str                             header;
        System.Net.HttpWebRequest       httpRequest;
        System.Net.HttpWebResponse      httpResponse;
        System.Net.WebHeaderCollection  headers;
        CLRObject                       clro;
    
        int batchSize = 1024;
        System.IO.Stream receiveStream;
        System.IO.StreamReader readStream;
        System.Text.Encoding encode;
        System.Char[] read;
        System.Text.StringBuilder sb;
        System.String readString;
        str contentEncoding;
    
        int countRead;
    
        ;
    
        url = "https://api.dachser.com/rest/v2/shipmenthistory?tracking-number=3616047827517440";
        method = "GET";
    
        try
        {
            clro         = System.Net.WebRequest::Create(url);
            httpRequest  = clro;
    
            headers = new System.Net.WebHeaderCollection();
            headers.Add("X-IBM-Client-Id", "77079f46c44fd809905968e00edc7eec");
            headers.Add("Accept-Language", "fr");
    
            httpRequest.set_Headers(headers);
            httpRequest.set_Method(method);
            httpRequest.set_ContentType("application/json");
    
            httpResponse = httpRequest.GetResponse();
    
            if (httpResponse)
            {
                receiveStream = httpResponse.GetResponseStream();
                contentEncoding = httpResponse.get_ContentEncoding();
    
                if (contentEncoding)
                {
                    encode = System.Text.Encoding::GetEncoding(contentEncoding);
                }
                else
                {
                    encode = new System.Text.UTF8Encoding();
                }
    
                readStream = new System.IO.StreamReader(receiveStream, encode);
                read = new System.Char[batchSize]();
    
                countRead = readStream.Read(read, 0, batchSize);
    
                sb = new System.Text.StringBuilder();
                while (countRead > 0)
                {
                    readString = new System.String(read, 0, countRead);
                    sb.Append(readString);
                    countRead = readStream.Read(read, 0, batchSize);
                }
    
                readStream.Close();
    
                info(sb.ToString());
            }
        }
        catch(Exception::CLRError)
        {
            throw error(AifUtil::getClrErrorMessage());
        }
    
    }

    Thanks a lot

  • Martin Dráb Profile Picture
    237,965 Most Valuable Professional on at

    You need a (de)serializer - I suggested using Newtonsoft.Json.

    I would create a method inside the C# library to accepting a string and returning an instance of the Rootobject class. For example:

    using Newtownsoft.Json;
    
    namespace JSONLibrary
    {
    	public class Shipments
    	{
    		public static Rootobject Deserialize(string json)
    		{
    			return JsonConvert.DeserializeObject(json);
    		}
    	}
    }

    By the way, I would rename Rootobject to something descriptive.

    Then call this method from X . You'll pass in the JSON string and you'll get Rootobject.

    JSONLibrary.Rootobject rootObject;
    ...
    json = readStream.ReadToEnd();
    rootObject = JSONLibrary.Shipments::Deserialize(json);

    By the way, you need to declare variables just for those objects that you'll refer to in your code.

  • mimi51340 Profile Picture
    50 on at

    which one am I supposed to use ?

    2022_2D00_01_2D00_27_5F00_15_2D00_20_2D00_43.png

    And in addition, do I need to create a method for every node ? for example, shipmentdate, shipmentweight, consignor... ?

    Thanks

  • Martin Dráb Profile Picture
    237,965 Most Valuable Professional on at

    AX 2009 uses .NET Framework 3.5.

  • mimi51340 Profile Picture
    50 on at

    Thanks do I need to create a method for every node ? for example, shipmentdate, shipmentweight, consignor... ?

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > Finance | Project Operations, Human Resources, AX, GP, SL

#1
Martin Dráb Profile Picture

Martin Dráb 551 Most Valuable Professional

#2
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 450 Super User 2025 Season 2

#3
BillurSamdancioglu Profile Picture

BillurSamdancioglu 278 Most Valuable Professional

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans