20.12.2016, 14:41 | #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. все верно, или есть варианты лучше? |
|
20.12.2016, 15:25 | #2 |
Модератор
|
JSON потому что это круто / модно / по каким-то еще причинам ? 100% нужен HTTP адаптер и соответственно дополнительная прослойка в виде IIS ? Есть хотя бы теоретическая вероятность научить приложение "на той стороне" работать с nettcp binding-ами ?
__________________
-ТСЯ или -ТЬСЯ ? |
|
20.12.2016, 16:08 | #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. |
|
20.12.2016, 20:29 | #4 |
Модератор
|
ну тут наверное надо в идеале Максима саммонить, но он сильно занят сейчас, насколько я понимаю
__________________
-ТСЯ или -ТЬСЯ ? |
|
09.02.2017, 15:43 | #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). |
09.02.2017, 15:53 | #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 |
|
09.02.2017, 17:47 | #7 |
Участник
|
Ага, спасибо. Для 4.0 сделал web-сервис, который принимает json и конвертирует его в XML с помощью Json.NET. Дальше передаю эту XML в аксапту через бизнес-коннектор, там обрабатываю и возвращаю результат в виде строки json. Можно возвращать и XML, но структура достаточно простая, чтобы этим не заморачиваться, плюс лишние конвертации повлияют на время отклика.
Насчет 12 пока думаю - использовать AIF или работать как с 4.0, пока склоняюсь к варианту со своим сервисом. |
|
09.02.2017, 18:52 | #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). |
27.02.2017, 13:01 | #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). |
05.07.2017, 15:25 | #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. |
|
05.07.2017, 16:39 | #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). |
05.07.2017, 16:54 | #12 |
Участник
|
Обертка не должна влиять. У нас тоже была обертка. Я для форума пример выложил без обертки, чтобы проще понимать и воспроизводить баг.
Код выполняется под CIL ? Возможно с этим связано. writer в вашем случае это объект какого типа ? В моем случае проблема была в том что писали 268.17 а выводилось 268.16999999999996 Хотя для других чисел было нормально. Попробуйте вывести именно 268.17 Последний раз редактировалось Logger; 05.07.2017 в 17:07. |
|
06.07.2017, 15:42 | #13 |
Участник
|
Взял код из джоба "Job3991_axforum", не воспроизвелась проблема.
Возможно дело в версии dll'ки? |
|
06.07.2017, 15:51 | #14 |
Участник
|
Проверю под 2012-й, вы ведь на 2012-й пробовали ?
Я проверял под 2009-й. |
|
06.07.2017, 16:34 | #15 |
Участник
|
Да, из под 6.2.3000.110, с dll для .Net 4.5 v10.0.3.21018
|
|
|
За это сообщение автора поблагодарили: Logger (3). |
Теги |
aif, ax2012, azure service bus, json, округление |
|
|