Skip to main content

Notifications

Announcements

No record found.

Microsoft Dynamics AX forum
Answered

Rewriting HTTP request from CURL to X++

Posted on by 25

Hi! I'm a bit stuck with the same problem, need to translate to x++ this cURL request:

curl -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Token ${API_KEY}" \
-d '{ "query": "my query text" }' \
https://myawesomeservice.com

I can't understand, how to add to RetailWebRequest the payload - query - and Authorisation token - API_KEY.

Maybe, you have any ideas?
  • Martin Dráb Profile Picture
    Martin Dráb 225,490 Super User on at
    RE: Rewriting HTTP request from CURL to X++

    I think that your code throws an exception, but you aren't aware of it because you don't catch managed exceptions.

    Put your code to a try/catch block like this and try it again:

    try
    {
        ... your code ...
    }
    catch (Exception::CLRError)
    {
        throw error(AifUtil::getClrErrorMessage());
    }

  • CSafwat Profile Picture
    CSafwat 90 on at
    RE: Rewriting HTTP request from CURL to X++

    Hello, I tried the same code but it's not working. I tried to debug the code, the debug stop on line 30 without any error!

    Do you have any idea what could be the problem? 

    System.Net.HttpWebRequest		webRequest;
    System.Net.HttpWebResponse      webResponse;
    System.IO.Stream                stream;
    System.IO.StreamReader          streamReader;
    System.Byte[]                   bytes;
    System.Net.WebHeaderCollection  headers;
    str                             response;
    System.Text.UTF8Encoding        encoding;
    str                             apiKey = 'My API Key';
    ;
    new InteropPermission(InteropKind::ClrInterop).assert();
    webRequest = System.Net.WebRequest::Create('myawesomeservice.com') as System.Net.HttpWebRequest;
    
    //Making header collection and setting the requisites
    headers = new System.Net.WebHeaderCollection();
    headers.Add("Authorization: Token "   apiKey);
    webRequest.set_Headers(headers);
    webRequest.set_Method('POST');
    webRequest.set_ContentType('application/json');
    webRequest.set_Accept('application/json');
    webRequest.set_Timeout(5000);
    
    //setting encoding
    encoding    = new System.Text.UTF8Encoding();
    bytes       = encoding.GetBytes('{ "query": "my query text" }');
    webRequest.set_ContentLength(bytes.get_Length());
    stream = webRequest.GetRequestStream();
    stream.Write(bytes, 0, bytes.get_Length());
    stream.Close();
    webResponse		= webRequest.GetResponse();
    stream          = webResponse.GetResponseStream();
    streamReader    = new System.IO.StreamReader(stream);
    response        = streamReader.ReadToEnd();
    streamReader.Close();
    stream.Close();
    
    CodeAccessPermission::revertAssert();

  • Martin Dráb Profile Picture
    Martin Dráb 225,490 Super User on at
    RE: Rewriting HTTP request from CURL to X++

    Thank you for sharing!

    By the way, please use Insert > Insert Code (in the rich-formatting view) to paste source code; it's then easier to read:

    System.Net.HttpWebRequest		webRequest;
    System.Net.HttpWebResponse      webResponse;
    System.IO.Stream                stream;
    System.IO.StreamReader          streamReader;
    System.Byte[]                   bytes;
    System.Net.WebHeaderCollection  headers;
    str                             response;
    System.Text.UTF8Encoding        encoding;
    str                             apiKey = 'My API Key';
    ;
    new InteropPermission(InteropKind::ClrInterop).assert();
    webRequest = System.Net.WebRequest::Create('myawesomeservice.com') as System.Net.HttpWebRequest;
    
    //Making header collection and setting the requisites
    headers = new System.Net.WebHeaderCollection();
    headers.Add("Authorization: Token "   apiKey);
    webRequest.set_Headers(headers);
    webRequest.set_Method('POST');
    webRequest.set_ContentType('application/json');
    webRequest.set_Accept('application/json');
    webRequest.set_Timeout(5000);
    
    //setting encoding
    encoding    = new System.Text.UTF8Encoding();
    bytes       = encoding.GetBytes('{ "query": "my query text" }');
    webRequest.set_ContentLength(bytes.get_Length());
    stream = webRequest.GetRequestStream();
    stream.Write(bytes, 0, bytes.get_Length());
    stream.Close();
    webResponse		= webRequest.GetResponse();
    stream          = webResponse.GetResponseStream();
    streamReader    = new System.IO.StreamReader(stream);
    response        = streamReader.ReadToEnd();
    streamReader.Close();
    stream.Close();
    
    CodeAccessPermission::revertAssert();

    And consider closing resources (such as streams) even if an exception is thrown. It's easier in C# (and D365FO) with using blocks (or finally), but it can be done in AX 2012 as well by calling Close() from both the happy path and in a catch block.

  • Suggested answer
    Mikhail Bulanov Profile Picture
    Mikhail Bulanov 25 on at
    RE: Rewriting HTTP request from CURL to X++

    Thanks for your adivces, Martin, I'll use this approach on other projects.

    For now, I came to this solution, may be, it would be useful for someone

       System.Net.HttpWebRequest           webRequest;

       System.Net.HttpWebResponse         webResponse;

       System.IO.Stream                              stream;

       System.IO.StreamReader                   streamReader;

       System.Byte[]                                     bytes;

       System.Net.WebHeaderCollection     headers;

       str                                                       response;

       System.Text.UTF8Encoding                encoding;

       str                                                      apiKey = 'My API Key';

       ;

           new InteropPermission(InteropKind::ClrInterop).assert();

           webRequest = System.Net.WebRequest::Create('myawesomeservice.com') as  System.Net.HttpWebRequest;

           //Making header collection and setting the requisites

           headers = new System.Net.WebHeaderCollection();

           headers.Add("Authorization: Token " + apiKey);

           webRequest.set_Headers(headers);

           webRequest.set_Method('POST');

           webRequest.set_ContentType('application/json');

           webRequest.set_Accept(''application/json'');

           webRequest.set_Timeout(5000);

           //setting encoding

           encoding    = new System.Text.UTF8Encoding();

           bytes       = encoding.GetBytes("{ \"query\": \"my query text\" }");

           webRequest.set_ContentLength(bytes.get_Length());

           stream = webRequest.GetRequestStream();

           stream.Write(bytes, 0, bytes.get_Length());

           stream.Close();

           webResponse         = webRequest.GetResponse();

           stream                   = webResponse.GetResponseStream();

           streamReader        = new System.IO.StreamReader(stream);

           response                = streamReader.ReadToEnd();

           streamReader.Close();

           stream.Close();

           CodeAccessPermission::revertAssert();

  • Verified answer
    Martin Dráb Profile Picture
    Martin Dráb 225,490 Super User on at
    RE: Rewriting HTTP request from CURL to X++

    I don't think that rewriting it to X++ is a good idea. It'll take time and the resulting code will be worse. Less powerful, more complicated and harder to read.

    Why you don't you simply create a C# class library with this code, add it to AOT and set it to be deployed automatically where you need it? Then you'll simply call the library from X++.

    It's not third-party component; just .NET and your code.

    Note that HttpClient client is just one of the available classes. You can successfully use HttpWebRequest too, or anything else.

  • Mikhail Bulanov Profile Picture
    Mikhail Bulanov 25 on at
    RE: Rewriting HTTP request from CURL to X++

    Thank you for this example, I will try to rewrite it to X++.

  • Mikhail Bulanov Profile Picture
    Mikhail Bulanov 25 on at
    RE: Rewriting HTTP request from CURL to X++

    Thanks, Martin! Sorry, I didn't elaborate: I use Dynamics Ax 2012 R3. To be honest, I don't have a lot of preferences, justed wanted to avoid using external third-party components. RetailWebRequest was my first guess, the second thought was using System.Net.HttpWebRequest

  • Martin Dráb Profile Picture
    Martin Dráb 225,490 Super User on at
    RE: Rewriting HTTP request from CURL to X++

    For example, with HttpClient, it could look like this:

    using (HttpClient client = new HttpClient())
    {
    	client.DefaultRequestHeaders.Add("Authorization", $"Token {API_KEY}" );
    	client.DefaultRequestHeaders.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    	 
    	HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post,
    														"https://myawesomeservice.com");
    	
    	var contract = new { query = "my query text" };
    	request.Content = new StringContent(JsonConvert.SerializeObject(contract),
    										Encoding.UTF8,
    										"application/json");
    									
    	var result = client.SendAsync(request).Result;
    	
    	if (result.IsSuccessStatusCode)
    	{
    		...
    	}
    }

    This is C# code (you can call your own C# libraries from X ). Rewriting it to X is possible (more or less, it depends on the version), but you couldn't use the anonymous object (line 9).

  • Martin Dráb Profile Picture
    Martin Dráb 225,490 Super User on at
    RE: RE: Json API Get and POST methods in X++ with API Key Authorization

    The X++ class RetailWebRequest seems to support a single header only, therefore it doesn't look suitable for your scenario. Although RetailCommonWebAPI may add some extra headers (I don't know without checking the code). Is there any reason why you want to use RetailWebRequest, except of that it looked useful?

  • Martin Dráb Profile Picture
    Martin Dráb 225,490 Super User on at
    RE: RE: Json API Get and POST methods in X++ with API Key Authorization

    Hi Mikhail, I moved your question to a separate thread.

    Which version of AX are you using?

    -H is used for headers.

    -d goes to the body.

    In X++, you'll use one of .NET classes for this purpose; implementation details depend on this decision. Do you have any preference?

Helpful resources

Quick Links

Replay now available! Dynamics 365 Community Call (CRM Edition)

Catch up on the first D365 Community Call held on 7/10

Community Spotlight of the Month

Kudos to Saurav Dhyani!

Congratulations to the June Top 10 community leaders!

These stars go above and beyond . . .

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 287,696 Super User

#2
Martin Dráb Profile Picture

Martin Dráb 225,490 Super User

#3
nmaenpaa Profile Picture

nmaenpaa 101,148

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans