|
|
#1 |
|
Участник
|
AIF + Web Services + JSON
Приветствую!
Начал разбираться с AIF и web-сервисами в Ax2012 и прошу подсказать некоторые вещи. Хочу настроить обмен данными со сторонним приложением посредством JSON (мастер-данные, создание заказов, запрос остатков) По умолчанию сервисы в аксапте используют SOAP+WSDL. Мне, похоже, нужен RESTFul+JSON Как понял, последовательность действий такая: Создаем свой Custom Inbound AIF Service, адаптер вида HTTP. Создаем класс контракта и класс сервиса Нужно переписать класс web-сервиса, чтобы вместо WDSL он отдавал JSON (например так https://community.dynamics.com.nsatc.../f/33/t/126680) Чтобы сервис принимал JSON нужно переписать класс контракта, чтобы он умел парсить JSON. все верно, или есть варианты лучше? |
|
|
|
|
#2 |
|
Модератор
|
JSON потому что это круто / модно / по каким-то еще причинам ? 100% нужен HTTP адаптер и соответственно дополнительная прослойка в виде IIS ? Есть хотя бы теоретическая вероятность научить приложение "на той стороне" работать с nettcp binding-ами ?
__________________
-ТСЯ или -ТЬСЯ ? |
|
|
|
|
#3 |
|
Участник
|
Цитата:
HTTP адаптер это промежуточная DLL-ка к каждому сервису? нашел интересное сообщение у Maxim Gorbunov "делал интеграцию на AIF, которая обменивалась JSON-сообщениями. И даже не так сильно пришлось допиливать AIF. Если б проект был на AX2012, то и вообще бы не пришлось ничего пилить" Интеграция - использовать стандарт или писать на коленке ? звучит очень интересно, но из конкретики пока нашел только в "Developing secure mobile apps for Microsoft Dynamics AX 2012. White Paper" описание: creating a RESTful service by using WCF через AIF Windows Azure Service Bus Adapter но пока непонятно ,что за зверушка этот Bus Adapter upd: No it is not possible to install the service bus on a Windows Server 2012. The companion apps are connecting to the Azure servicebus online поэтому эта шина не подойдет Последний раз редактировалось AlexeyS; 20.12.2016 в 16:29. |
|
|
|
|
#4 |
|
Модератор
|
ну тут наверное надо в идеале Максима саммонить, но он сильно занят сейчас, насколько я понимаю
__________________
-ТСЯ или -ТЬСЯ ? |
|
|
|
|
#5 |
|
Administrator
|
Цитата:
Сообщение от AlexeyS
Как понял, последовательность действий такая:
Создаем свой Custom Inbound AIF Service, адаптер вида HTTP. Создаем класс контракта и класс сервиса Нужно переписать класс web-сервиса, чтобы вместо WDSL он отдавал JSON (например так https://community.dynamics.com.nsatc.../f/33/t/126680) Чтобы сервис принимал JSON нужно переписать класс контракта, чтобы он умел парсить JSON. все верно, или есть варианты лучше? Для конвертации JSON и XML я пользовался Newtonsoft Json.NET (http://www.newtonsoft.com/json). Сначала была идея стандартным дот-нетовским сериалайзером пользоваться, но для него надо все контракты явно прописать. С точки зрения контроля над разработкой так, наверное, правильнее, но решение менее гибким становится. В общем, смотрите сами. Если есть ещё вопросы, задавайте. Помогу чем смогу
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
|
|
| За это сообщение автора поблагодарили: AlexeyS (3), Logger (1), alex55 (1). | |
|
|
#6 |
|
Administrator
|
Цитата:
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
|
|
|
#7 |
|
Участник
|
Ага, спасибо. Для 4.0 сделал web-сервис, который принимает json и конвертирует его в XML с помощью Json.NET. Дальше передаю эту XML в аксапту через бизнес-коннектор, там обрабатываю и возвращаю результат в виде строки json. Можно возвращать и XML, но структура достаточно простая, чтобы этим не заморачиваться, плюс лишние конвертации повлияют на время отклика.
Насчет 12 пока думаю - использовать AIF или работать как с 4.0, пока склоняюсь к варианту со своим сервисом. |
|
|
|
|
#8 |
|
Administrator
|
Вот ещё посмотрите: https://github.com/ffilardi/axaptaapi/wiki
Это что-то вроде фреймворка для оборачивания аксаптовских SOAP-сервисов в RESTful интерфейсы.
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
|
|
| За это сообщение автора поблагодарили: mazzy (2), Diman (1). | |
|
|
#9 |
|
Участник
|
оставлю тут, вдруг кому пригодится:
Business connector кэширует данные, если было изменение класса, то можно почистить кэш, Код: axp = new Microsoft.Dynamics.BusinessConnectorNet.Axapta();
axp.Logon(null, null, null, null);
axp.CallStaticClassMethod("SysFlushAOD", "doFlush");Код: boolean getInfo()
{
boolean ret;
str url = "http://url.url";
CLRObject clrCredential = null;
System.Net.NetworkCredential credential = null;
CLRObject clro = null;
System.Net.HttpWebRequest httpRequest = null;
System.Net.HttpWebResponse httpResponse = null;
System.IO.Stream stream = null;
System.IO.StreamReader streamReader = null;
System.Xml.Linq.XNode xnode = null;
System.Exception clrException;
str s;
;
try
{
new InteropPermission(InteropKind::ClrInterop).assert();
clrCredential = new System.Net.NetworkCredential();
credential = clrCredential;
credential.set_UserName("user_name");
credential.set_Password("user_pwd");
clro = System.Net.WebRequest::Create(url);
httpRequest = clro;
httpRequest.set_Credentials(credential);
httpResponse = httpRequest.GetResponse();
stream = httpResponse.GetResponseStream();
streamReader = new System.IO.StreamReader(stream);
s = streamReader.ReadToEnd();
if (s == "null" || s == "false")
{
info("No info");
ret = false;
}
else
{
xnode = Newtonsoft.Json.JsonConvert::DeserializeXNode(s, "Root");
s = xNode.ToString();
xmlDoc = new XMLDocument();
xmlDoc.loadXml(s);
CodeAccessPermission::revertAssert();
ret = true;
}
}
catch(Exception::CLRError)
{
clrException = CLRInterop::getLastException();
if (clrException)
{
clrException = clrException.get_InnerException();
if (clrException)
{
error(clrException.get_Message());
}
}
ret = false;
}
return ret;
} |
|
|
|
| За это сообщение автора поблагодарили: Vadik (1), trud (2), Logger (10), Ace of Database (3). | |
|
|
#10 |
|
Участник
|
Этот Newtonsoft.Json имеет проблемы при передаче из аксапты real типа. Т.е. всех суммовых значений.
![]() Вот пример X++: static void Job3991_axforum(Args _args) { GRD_JsonWriter jsonWriter; real r; System.Double netDouble; System.Single netSingle; System.Decimal netDecimal; str ret; Newtonsoft.Json.Linq.JTokenWriter writer; Newtonsoft.Json.Linq.JObject jObject; ClrObject clrObject; System.Globalization.NumberFormatInfo numinf; ; r = 268.17; writer = new Newtonsoft.Json.Linq.JTokenWriter(); writer.WriteStartObject(); writer.WritePropertyName("params"); writer.WriteStartObject(); writer.WritePropertyName("VATAmount_xppReal"); writer.WriteValue(r); writer.WritePropertyName("VATAmount_Row"); writer.WriteRawValue("268.17"); netDouble = r; writer.WritePropertyName("VATAmount_netDouble"); writer.WriteValue(netDouble); netSingle = r; writer.WritePropertyName("VATAmount_netSingle"); writer.WriteValue(netSingle); netDecimal = New System.Decimal(netDouble); writer.WritePropertyName("VATAmount_netDecimalViaDouble"); writer.WriteValue(netDecimal); netDecimal = New System.Decimal(netSingle); writer.WritePropertyName("VATAmount_netDecimalViaSingle"); writer.WriteValue(netDecimal); numinf = new System.Globalization.NumberFormatInfo(); numinf.set_NumberDecimalSeparator("."); netDecimal = System.Decimal::Parse("268.17", numinf); info(CLRInterop::getAnyTypeForObject(netDecimal)); writer.WritePropertyName("VATAmount_netDecimal"); writer.WriteValue(netDecimal); writer.WriteEndObject(); writer.WriteEndObject(); clrObject = writer.get_Token(); jObject = clrObject; ret = jObject.ToString(); info(ret); } Цитата:
{
"params": { "VATAmount_xppReal": 268.16999999999996, "VATAmount_Row": 268.17, "VATAmount_netDouble": 268.16999999999996, "VATAmount_netSingle": 268.16999999999996, "VATAmount_netDecimalViaDouble": 268.17, "VATAmount_netDecimalViaSingle": 268.17, "VATAmount_netDecimal": 268.17 } } Приходится данные через System.Decimal передавать. Или самим значение параметра в строку конвертировать и пихать туда через WriteRawValue Последний раз редактировалось Logger; 05.07.2017 в 15:45. |
|
|
|
|
#11 |
|
Участник
|
Я вот этот метод использую -
Write JSON with JsonTextWriter real пишется так - X++: public void WriteDecimalField(str propName, real value) { ; writer.WritePropertyName(propName); writer.WriteValue(value); } X++: static void Job38(Args _args) { JSONWriter writerWrapper = JSONWriter::construct(); real a = 123.567; writerWrapper.WriteStartObject(); writerWrapper.WriteDecimalField("Ax_real_", a); writerWrapper.WriteEndObject(); info(writerWrapper.getJson()); } PHP код:
__________________
AxAssist 2012 - Productivity Tool for Dynamics AX 2012/2009/4.0/3.0 |
|
|
|
| За это сообщение автора поблагодарили: Logger (10). | |
|
|
#12 |
|
Участник
|
Обертка не должна влиять. У нас тоже была обертка. Я для форума пример выложил без обертки, чтобы проще понимать и воспроизводить баг.
Код выполняется под CIL ? Возможно с этим связано. writer в вашем случае это объект какого типа ? В моем случае проблема была в том что писали 268.17 а выводилось 268.16999999999996 Хотя для других чисел было нормально. Попробуйте вывести именно 268.17 Последний раз редактировалось Logger; 05.07.2017 в 17:07. |
|
|
|
|
#13 |
|
Участник
|
Взял код из джоба "Job3991_axforum", не воспроизвелась проблема.
Возможно дело в версии dll'ки? |
|
|
|
|
#14 |
|
Участник
|
Проверю под 2012-й, вы ведь на 2012-й пробовали ?
Я проверял под 2009-й. |
|
|
|
|
#15 |
|
Участник
|
Да, из под 6.2.3000.110, с dll для .Net 4.5 v10.0.3.21018
|
|
|
|
| За это сообщение автора поблагодарили: Logger (3). | |
| Теги |
| aif, ax2012, azure service bus, json, округление |
|
|
|