AXForum  
Zurück   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Kennwort vergessen?
Registrieren Forum Rules Hilfe Benutzerliste Heutige Beiträge Suchen Alle Foren als gelesen markieren

 
 
Themen-Optionen Thema durchsuchen Ansicht
Alt 20.12.2016, 14:41   #1  
AlexeyS ist offline
AlexeyS
Участник
 
404 / 339 (12) ++++++
Registriert seit: 15.06.2004
Ort: москва
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.
все верно, или есть варианты лучше?
Alt 20.12.2016, 15:25   #2  
Vadik ist offline
Vadik
Модератор
Benutzerbild von Vadik
Лучший по профессии 2017
Лучший по профессии 2015
 
3.631 / 1853 (69) ++++++++
Registriert seit: 18.11.2002
Ort: гражданин Москвы
Zitat:
Zitat von AlexeyS Beitrag anzeigen
все верно, или есть варианты лучше?
JSON потому что это круто / модно / по каким-то еще причинам ? 100% нужен HTTP адаптер и соответственно дополнительная прослойка в виде IIS ? Есть хотя бы теоретическая вероятность научить приложение "на той стороне" работать с nettcp binding-ами ?
__________________
-ТСЯ или -ТЬСЯ ?
Alt 20.12.2016, 16:08   #3  
AlexeyS ist offline
AlexeyS
Участник
 
404 / 339 (12) ++++++
Registriert seit: 15.06.2004
Ort: москва
Zitat:
Zitat von Vadik Beitrag anzeigen
JSON потому что это круто / модно / по каким-то еще причинам ? 100% нужен HTTP адаптер и соответственно дополнительная прослойка в виде IIS ? Есть хотя бы теоретическая вероятность научить приложение "на той стороне" работать с nettcp binding-ами ?
предстоит интегрироваться с приложением на андроиде (еще не написанном) и сторонние разработчики очень хотят json.
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
поэтому эта шина не подойдет

Geändert von AlexeyS (20.12.2016 um 16:29 Uhr)
Alt 20.12.2016, 20:29   #4  
Vadik ist offline
Vadik
Модератор
Benutzerbild von Vadik
Лучший по профессии 2017
Лучший по профессии 2015
 
3.631 / 1853 (69) ++++++++
Registriert seit: 18.11.2002
Ort: гражданин Москвы
Zitat:
Zitat von AlexeyS Beitrag anzeigen
нашел интересное сообщение у Maxim Gorbunov "делал интеграцию на AIF, которая обменивалась JSON-сообщениями. И даже не так сильно пришлось допиливать AIF. Если б проект был на AX2012, то и вообще бы не пришлось ничего пилить"
ну тут наверное надо в идеале Максима саммонить, но он сильно занят сейчас, насколько я понимаю
__________________
-ТСЯ или -ТЬСЯ ?
Alt 09.02.2017, 15:43   #5  
Maxim Gorbunov ist offline
Maxim Gorbunov
Administrator
Соотечественники
Лучший по профессии 2009
 
2.483 / 646 (26) +++++++
Registriert seit: 27.11.2001
Ort: Dubai, UAE
Zitat:
Zitat von AlexeyS Beitrag anzeigen
Как понял, последовательность действий такая:
Создаем свой Custom Inbound AIF Service, адаптер вида HTTP.
Создаем класс контракта и класс сервиса
Нужно переписать класс web-сервиса, чтобы вместо WDSL он отдавал JSON (например так https://community.dynamics.com.nsatc.../f/33/t/126680)
Чтобы сервис принимал JSON нужно переписать класс контракта, чтобы он умел парсить JSON.
все верно, или есть варианты лучше?
Можно и так, но, как мне кажется, проще просто приделать transformation на inbound port. Я делал .NET трансформации, которые конвертировали JSON-сообщения в XML и передавали их дальше в AIF. Там (в inbound pipeline) уже делал XSLT, чтобы привести XML к схеме, которая в AIF используется.

Для конвертации 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
This post has been rated by: AlexeyS (3), Logger (1), alex55 (1).
Alt 09.02.2017, 15:53   #6  
Maxim Gorbunov ist offline
Maxim Gorbunov
Administrator
Соотечественники
Лучший по профессии 2009
 
2.483 / 646 (26) +++++++
Registriert seit: 27.11.2001
Ort: Dubai, UAE
Zitat:
Zitat von AlexeyS Beitrag anzeigen
creating a RESTful service by using WCF через AIF Windows Azure Service Bus Adapter
Не совсем понял, о каком White Paper речь. Если про вот это - Developing Mobile Apps - насколько я понял, там идея в том, что предлагается написать на .NET промежуточный WCF сервис, у которого будет RESTful endpoint и который будет принимать сообщения, заворачивать их в SOAP-конверт и отправлять в AIF. В принципе, тоже вариант, но понятно, что администрировать это будет немного сложнее. Ну и, опять же, вопрос гибкости: расширять решение будет немного сложнее.
__________________
Not registered yet? Register here!
Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me
Alt 09.02.2017, 17:47   #7  
AlexeyS ist offline
AlexeyS
Участник
 
404 / 339 (12) ++++++
Registriert seit: 15.06.2004
Ort: москва
Ага, спасибо. Для 4.0 сделал web-сервис, который принимает json и конвертирует его в XML с помощью Json.NET. Дальше передаю эту XML в аксапту через бизнес-коннектор, там обрабатываю и возвращаю результат в виде строки json. Можно возвращать и XML, но структура достаточно простая, чтобы этим не заморачиваться, плюс лишние конвертации повлияют на время отклика.
Насчет 12 пока думаю - использовать AIF или работать как с 4.0, пока склоняюсь к варианту со своим сервисом.
Alt 09.02.2017, 18:52   #8  
Maxim Gorbunov ist offline
Maxim Gorbunov
Administrator
Соотечественники
Лучший по профессии 2009
 
2.483 / 646 (26) +++++++
Registriert seit: 27.11.2001
Ort: Dubai, UAE
Вот ещё посмотрите: 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
This post has been rated by: mazzy (2), Diman (1).
Alt 27.02.2017, 13:01   #9  
AlexeyS ist offline
AlexeyS
Участник
 
404 / 339 (12) ++++++
Registriert seit: 15.06.2004
Ort: москва
оставлю тут, вдруг кому пригодится:

Business connector кэширует данные, если было изменение класса, то можно почистить кэш,
Code:
axp = new Microsoft.Dynamics.BusinessConnectorNet.Axapta();
axp.Logon(null, null, null, null);
axp.CallStaticClassMethod("SysFlushAOD", "doFlush");
обращение к сервису из аксапты, получение JSON и конвертация в XML
Code:
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;
}
This post has been rated by: Vadik (1), trud (2), Logger (10), Ace of Database (3).
Alt 05.07.2017, 15:25   #10  
Logger ist offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3.996 / 3293 (117) ++++++++++
Registriert seit: 12.10.2004
Ort: Москва
Blog-Einträge: 2
Этот 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);

}
На выходе дает
Zitat:
{
"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

Geändert von Logger (05.07.2017 um 15:45 Uhr)
Alt 05.07.2017, 16:39   #11  
Alex_KD ist offline
Alex_KD
Участник
AxAssist
MCBMSS
Соотечественники
 
522 / 362 (14) ++++++
Registriert seit: 06.07.2006
Ort: Melbourne, Down Under
Я вот этот метод использую -
Write JSON with JsonTextWriter

real пишется так -

X++:
public void WriteDecimalField(str propName, real value)
{
    ;
    writer.WritePropertyName(propName);
    writer.WriteValue(value);
}
Завернул все в класс-обертку JSONWriter.
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-Code:
{
  
"Ax_real_"123.567

Имейте ввиду что скорость в CIL примерно в 1000-10000 раз быстрее. В целом пишет ооочень быстро.
__________________
AxAssist 2012 - Productivity Tool for Dynamics AX 2012/2009/4.0/3.0
This post has been rated by: Logger (10).
Alt 05.07.2017, 16:54   #12  
Logger ist offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3.996 / 3293 (117) ++++++++++
Registriert seit: 12.10.2004
Ort: Москва
Blog-Einträge: 2
Обертка не должна влиять. У нас тоже была обертка. Я для форума пример выложил без обертки, чтобы проще понимать и воспроизводить баг.
Код выполняется под CIL ?
Возможно с этим связано.
writer в вашем случае это объект какого типа ?

В моем случае проблема была в том что писали 268.17 а выводилось 268.16999999999996
Хотя для других чисел было нормально.
Попробуйте вывести именно 268.17

Geändert von Logger (05.07.2017 um 17:07 Uhr)
Alt 06.07.2017, 15:42   #13  
Товарищ ♂uatr ist offline
Товарищ ♂uatr
Участник
Benutzerbild von Товарищ ♂uatr
MCBMSS
 
337 / 915 (31) +++++++
Registriert seit: 23.10.2012
Взял код из джоба "Job3991_axforum", не воспроизвелась проблема.
Возможно дело в версии dll'ки?
Alt 06.07.2017, 15:51   #14  
Logger ist offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3.996 / 3293 (117) ++++++++++
Registriert seit: 12.10.2004
Ort: Москва
Blog-Einträge: 2
Проверю под 2012-й, вы ведь на 2012-й пробовали ?
Я проверял под 2009-й.
Alt 06.07.2017, 16:34   #15  
Товарищ ♂uatr ist offline
Товарищ ♂uatr
Участник
Benutzerbild von Товарищ ♂uatr
MCBMSS
 
337 / 915 (31) +++++++
Registriert seit: 23.10.2012
Да, из под 6.2.3000.110, с dll для .Net 4.5 v10.0.3.21018
This post has been rated by: Logger (3).
Stichworte
aif, ax2012, azure service bus, json, округление

 

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
daxdilip: How to: Configure Dynamics AX AIF Services to listen for SSL Requests (https) Blog bot DAX Blogs 0 23.01.2011 10:12
emeadaxsupport: What changes are required if we change the Business Connector Proxy used by AX 2009 Generated AIF Web services Blog bot DAX Blogs 0 29.03.2010 15:05
Channel9: Microsoft Dynamics AX 2009 AIF Web Services Screencast Blog bot DAX Blogs 0 17.06.2009 17:05
axStart: InfoPath with default AIF web services Blog bot DAX Blogs 1 15.05.2008 02:27
Pokluda: Outbound web service (AIF) Blog bot DAX Blogs 0 28.10.2006 17:43
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Gehe zu

Рейтинг@Mail.ru
Alle Zeitangaben in WEZ +3. Es ist jetzt 04:10 Uhr.
Powered by vBulletin® Version 3.8.5 (Deutsch)
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.