One of the our customers of AX partner which I work AGC Software applied a service requires using Rest Api. I found different samples on forums and blogs about AX 2012 but succeeded none of them. At that point I dediced to start from beginning.
At first I installed Postman to my computer. Succeeded to run service with Postman.
Now I have C# RestSharp library code written by Postman's code generator:
I needed import RestSharp library into my project before have a code deployable by AX. When tried to import by command written in Visual Studio 2013 Package Manager Console :
Install-Package RestSharp
I got "The underlying connection was closed: An unexpected error occurred on a send." error. Found solution on a forum page. When i wrote code below to a .REG file and run than I could install Nuget packages:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
Learned last RestSharp version which works with Visual Studio 2013 from another forum page than I could import:
Install-Package RestSharp -Version 103.1.0
Now I had a working and deployable code with AX:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RestSharp;
namespace Ingenico
{
public class Ingenico
{
public string StartDate { get; set; }
public string EndDate { get; set; }
public string Body { get; set; }
public string Idx { get; set; }
public string getPaymentSummaryReport()
{
var client = new RestClient("https://XXXXXXXXXXXXXXX/GetPaymentSummaryReport");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Operator", "XXXXXXX");
request.AddHeader("Authorization", "Basic XXXXXXX");
request.AddHeader("Content-Type", "application/json");
Body = "{\r\n\"ReportId\": "+Idx+",\r\n\"SerialList\": [\r\n\"\"\r\n],\r\n\"StartDate\": \""+StartDate+
"\",\r\n\"EndDate\": \""+EndDate+
"\",\r\n\"ExternalField\": \"\",\r\n\"ReceiptNo\": 0,\r\n\"ZNo\":
0,\r\n\"GetSummary\": true,\r\n\"SaleFlags\": 0,\r\n\"DeviceGroupName\":
\"\"\r\n}\r\n \r\n";
request.AddParameter("application/json",Body, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
return response.Content;
}
}
}
When I deployed code, I saw it looks for RestSharp.DLL and RestSharp.XML files reside in project folder and AX doesn't copy them to bin folder. Copied these files to server and client bin folders:
Then I could use the service:
Ingenico.Ingenico o = new Ingenico.Ingenico();
str a;
try
{
o.set_StartDate("2020-10-01");
o.set_EndDate("2020-10-01");
o.set_Idx("111111111111");
a = o.getPaymentSummaryReport();
info(a);
I used another blog for parse Json string which came from service.
class AGCingenico
{
Array jsonArray;
}
At first parse Json string with this method:
void parseJson(str _json)
{
Array jsonArray;
container con;
int jsonSubstrNo, i;
TextBuffer textBuffer;
Array returnArray = new Array(Types::Class);
#Define.LBracket('{')
#Define.RBracket('}')
str st;
int fnd;
fnd = strScan(_json,"]",1,strLen(_json));
st="{"+subStr(_json,fnd+2,strlen(_json) - fnd -1);
con+=st;
// extract the json substrings and add them to a Array
textBuffer = new TextBuffer();
textBuffer.setText(_json);
while (textBuffer.nextToken(0, #LBracket+#RBracket))
{
if ((jsonSubstrNo mod 2) > 0)
{
st =#LBracket + textBuffer.token() + #RBracket;
con += st;
}
jsonSubstrNo++;
}
for (i = 1; i <= conLen(con); i++)
{
returnArray.value(i, RetailCommonWebAPI::getMapFromJsonString(conPeek(con, i)));
}
jsonArray = returnArray;
}
Than insert values a table with this method:
void jsonToTable()
{
MapIterator mi;
Map data;
int i;
str value;
for (i = 1; i <= jsonArray.lastIndex(); i++)
{
data = jsonArray.value(i);
mi = new MapIterator(data);
tmpTable.clear();
while (mi.more())
{
value = data.lookup(mi.key());
switch (mi.key())
{
case "ErrCode":
this.parmErrCode(str2int(value));
break;
case "ErrDesc":
this.parmErrStr(value);
break;
case "Amount":
tmpTable.Amount = str2num_RU(value);
break;
case "AmountCredit":
tmpTable.AmountCredit = str2num_RU(value);
break;
...
...
...
When I was thinking all well done there was another surprise. Code was working good with client side but not in CIL was giving an error about type convert. I found solution from a forum page again. Martin Drab described pinpoint solution. Modified RetailCommonWebAPI class like this and all errors was fixed:
//AGC memre 29.9.20
//private static Map getMap(CLRObject _dict)
private static Map getMap(System.Collections.IDictionary _dict)
//http://dev.goshoom.net/en/2016/01/x-to-cil-object-must-implement-iconvertible/#comment-135186
//AGC memre
{
At last it's easy to use Rest Api with AX 2012 but there're lots of issues need to touch, fortunately there're lots of forums pages and blogs. :)