Miklix

Вызов служб документов AIF напрямую из X++ в Dynamics AX 2012

Опубликовано: 16 февраля 2025 г. в 11:23:12 UTC
Последнее обновление: 12 января 2026 г. в 08:55:22 UTC

В этой статье я объясняю, как вызывать службы документов Application Integration Framework в Dynamics AX 2012 непосредственно из кода X++, эмулируя как входящие, так и исходящие вызовы, что может значительно упростить поиск и отладку ошибок в коде AIF.


Эта страница была переведена с английского языка для того, чтобы сделать ее доступной как можно большему числу людей. К сожалению, машинный перевод еще не является совершенной технологией, поэтому возможны ошибки. Если вы хотите, вы можете просмотреть оригинальную английскую версию здесь:

Calling AIF Document Services Directly from X++ in Dynamics AX 2012

Информация в этом сообщении основана на Dynamics AX 2012 R3. Она может быть или не быть актуальна для других версий.

Недавно я помогал клиенту внедрять входящий порт Application Integration Framework (AIF) для создания клиентов на основе данных, получаемых из другой системы. Поскольку Dynamics AX уже предоставляет службу документов CustCustomer, которая реализует эту логику, мы решили упростить задачу и использовать стандартное решение.

Однако вскоре выяснилось, что существует множество проблем с генерацией XML-файлов внешней системой, которые были бы приняты Dynamics AX. XML-схема, генерируемая Dynamics AX, довольно сложная, и, как оказалось, в Dynamics AX есть несколько ошибок, из-за которых система иногда отклоняет XML-файлы, которые, согласно другим инструментам, соответствуют схеме. Так что в целом, все оказалось не так просто, как я думал.

В ходе работы мне часто приходилось ломать голову над тем, в чем именно заключалась проблема с некоторыми XML-файлами, поскольку сообщения об ошибках, предоставляемые AIF, были недостаточно информативными. Это также было утомительно, потому что мне приходилось ждать, пока внешняя система отправит новое сообщение по MSMQ, а затем снова ждать, пока AIF получит и обработает это сообщение, прежде чем я смог увидеть ошибку.

Поэтому я исследовал, возможно ли вызывать код сервиса напрямую с помощью локального XML-файла для более быстрого тестирования, и оказалось, что это возможно — и не только это, это действительно просто сделать, и на самом деле это позволяет получать гораздо более информативные сообщения об ошибках.

Приведенный ниже пример задания считывает локальный XML-файл и пытается использовать его с классом AxdCustomer (который является классом документа, используемым службой CustCustomer) для создания клиента. При необходимости вы можете создать аналогичные задания для всех остальных классов документов, например, для AxdSalesOrder.

static void CustomerCreate(Args _args)
{
    FileNameOpen fileName    = @'C:\\TestCustomerCreate.xml';
    AxdCustomer  customer;
    AifEntityKey key;
    #File
    ;

    new FileIoPermission(fileName, #IO_Read).assert();

    customer = new AxdCustomer();

    key = customer.create(  XmlDocument::newFile(fileName).xml(),
                            new AifEndpointActionPolicyInfo(),
                            new AifConstraintList());

    CodeAccessPermission::revertAssert();

    info('Done');
}

Объект AifEntityKey, возвращаемый методом customer.create() (который соответствует операции создания сервиса в AIF), содержит информацию о том, какой клиент был создан, в том числе RecId созданной записи в CustTable.

Если вы пытаетесь протестировать исходящий порт или вам просто нужен пример того, как должен выглядеть XML-код на входящем порту, вы также можете использовать класс документа для экспорта данных клиента в файл, вызвав метод read() (соответствующий операции службы "чтение"), следующим образом:

static void CustomerRead(Args _args)
{
    FileNameSave    fileName = @'C:\\TestCustomerRead.xml';
    Map             map      = new Map( Types::Integer,
                                        Types::Container);
    AxdCustomer     customer;
    AifEntityKey    key;
    XMLDocument     xmlDoc;
    XML             xml;
    AifPropertyBag  bag;
    #File
    ;

    map.insert(fieldNum(CustTable, AccountNum), ['123456']);
    key = new AifEntityKey();
    key.parmTableId(tableNum(CustTable));
    key.parmKeyDataMap(map);
    customer = new AxdCustomer();

    xml = customer.read(key,
                        null,
                        new AifEndpointActionPolicyInfo(),
                        new AifConstraintList(),
                        bag);

    new FileIoPermission(fileName, #IO_Write).assert();
    xmlDoc = XmlDocument::newXml(xml);
    xmlDoc.save(fileName);
    CodeAccessPermission::revertAssert();
    info('Done');
}

Разумеется, вам следует заменить «123456» на номер счета клиента, данные которого вы хотите прочитать.

Дополнительное чтение

Если вам понравился этот пост, вам также могут понравиться эти предложения:


Поделиться на BlueskyПоделиться на FacebookПоделиться на LinkedInПоделиться на TumblrПоделиться на XПоделиться на LinkedInЗакрепить на Pinterest

Миккель Кристенсен

Об авторе

Миккель Кристенсен
Миккель - создатель и владелец сайта miklix.com. Он имеет более чем 20-летний опыт работы в качестве профессионального программиста/разработчика программного обеспечения и в настоящее время работает на полную ставку в крупной европейской IT-корпорации. Когда он не ведет блог, то тратит свое свободное время на огромное количество интересов, хобби и занятий, что в некоторой степени отражается в разнообразии тем, освещаемых на этом сайте.