| 
			
			 | 
		#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, округление | 
| 
	
	 | 
	
		
  |