C# в Microsoft Dynamics NAV 2009

Начнем издалека: в конце 2009 года Microsoft выпустил новую версию одного из своих бизнес-решений - Microsoft Dynamics NAV 2009. При сохранении функционала произошло значительное расширение технологических возможностей:

  • Трехзвенная архитектура (улучшена масштабируемость и безопасность решения)
  • Ролеориентированный клиент (гибкая настройка интерфейса для каждого пользователя)
  • Веб-службы (интеграция со сторонними приложениями)

Все это не могло не сказаться на внутренней организации решения. Так в частности Microsoft Dynamics NAV Server (не путать с Microsoft Dynamics NAV Database Server) не умеет исполнять код написанный на C/AL, более того он не понимает формы. Вместо этого Dynamics NAV Server неплохо умеет управляться с C# и WinForms.

Звучит круто, но если бы мне сказали, что завтра нужно программировать на C#… Нет, мир бы не остановился. Но пришлось бы несладко. Поэтому Microsoft подошел к этому деликатному вопросу очень аккуратно: разрешил программировать на C/AL, а работу по преобразованию C/AL в C# взял на себя.

Примечание: Если вы планируете продолжать использовать только классическую версию клиента, то выполнение компиляции в C# можно отключить – это позволит увеличить скорость импорта fob файлов. Для отключения компиляции в C# нужно щелкнуть File > Database > Alter, в окне Alter Database перейти на закладку Options и снять флажок в поле Enable for Microsoft Dynamics NAV Server. База должна быть в режиме Single User Mode (все вышесказанное относится к SQL версии).

При сохранении и компиляции объекта система, в лице классического клиента (разработка ведется в классическом клиенте), выполняет преобразование C/AL в C#. Данный C# код помещается в таблицу 2000000071 Object Metadata.
Таблица содержит следующие поля:

  • Object Type (option: TableData, Table, Form, Report, Dataport, Codeunit, XMLport, MenuSuite, Page, System, Field)
  • Object ID (integer)
  • Metadata (blob)
  • Version List (text)
  • User Code (blob)
  • Object Key (GUID)

Как нетрудно догадаться поля Object Type и Object ID входят в первичный ключ и позволяют однозначно идентифицировать объект. C# код находится в поле User Code.
При первом обращении одного из пользователей к какому-либо объекту (например, странице) Microsoft Dynamics NAV Server извлекает C# код из поля User Code соответствующей записи таблицы Object Metadata и компилирует его в MSIL. После чего исполняет код MSIL. Когда следующий пользователь обращается к тому же объекту, система сразу исполняет MSIL код.

Примечание. На самом деле система все же выполняет проверку – не был ли объект изменен. Для этого используются данные таблицы 2000000079 Object Tracking. Если объект был изменен, то система извлекает C# код из поля User Code и выполняет компиляцию в MSIL по новой.

Далее мы проведем небольшой, но крайне любопытный эксперимент.
Для начала создадим простую страницу:
1. В классическом клиенте щелкнуть Tools > Object Designer. Откроется окно Object Designer.
2. В окне Object Designer щелкнуть кнопку Page, чтобы открыть список страниц.
3. В окне Object Designer щелкнуть кнопку New, чтобы создать новую страницу. Для версии NAV 2009 SP1 появится окно мастера страниц.
4. В мастере страниц указать Table = Item, тип страницы = List.

Wizard

5. Щелкните кнопку ОК, чтобы перейти к следующему шагу.
6. Выберите поля No, Description и Base Unit of Measure

Wizard

7. Щелкните кнопку Finish, чтобы завершить работу мастера.
8. Страница должна выглядеть следующим образом:

Page Designer

9. В окне Page Designer перейдите на пустую строку и щелкните View > Properties. Откроется окно свойств.
10. В окне свойств установите значение Editable = No. Окно свойств для страницы должно быть таким:

Page Properties

Теперь добавим действия. Действия – это в некотором роде аналог функций.
1. В окне Page Designer перейдите на пустую строку и щелкните View > Actions. Откроется окно Action Designer.
2. В первой строке в поле Type выберите значение ActionContainer, в поле SubType выберите значение ActionItems. Поля Name и Caption оставьте пустыми – система заполнит их самостоятельно.
3. Во второй строке в поле Caption введите значение Message, в поле Type выберите значение Action. Окно Action Designer должно выглядеть так:

Action Designer

4. Станьте на вторую строку и щелкните View > Properties. Откроется окно свойств.
5. В окне свойств установите следующие значения свойств: Promoted = Yes, PromotedCategory = Process, PromotedIsBig = Yes. Окно свойств должно выглядеть так:

Action Properties

6. Закройте окно свойств, чтобы вернуться в Action Designer.
7. Станьте на вторую строку и щелкните View > C/AL Code. Откроется окноС/AL Editor.
8. В триггере onAction добавьте следующий код: MESSAGE(”No.”);
Сохраните страницу с ID = 50002, Name = Item List Lite, Compiled = Yes.
Откройте созданную страницу в ролеориентированном клиенте . Для этого в NAV 2009 SP1 щелкните кнопку Run, для NAV 2009 в окне Выполнить введите следующую команду DynamicsNAV:////runpage?page=50002.

Item List Lite

Отлично. Примитивная страница создана.
Пора приступить к исследованиям.

В качестве инструментария была создана специальная форма, задача которой выгружать данные из BLOB полей в файлы.
Как мы уже значем, C# код находится в поле User Code. Но что же находится в поле Metadata?
В поле Metadata содержится описание объекта, в нашем случае страницы, на языке XML.

XML Metadata

Что можно увидеть в данном файле?
Корневой тег PageDefinition содержит атрибуты ID = 50002 и Name = Item List Lite. На следующем уровне находится узел Properties, где в виде атрибутов и вложенных элементов указаны свойства страницы в целом. Сюда относятся атрибуты PageType и Editable, а также вложенный тег SourceObject.
На том же уровне, что и тег Properties находится тег Content, который повторяет структуру страницы, заданную в окна Page Designer.
Тег ActionContainers содержит описание действий и повторяет окно Action Designer. Обратите внимание, что в данном файле нет C# кода.

C# код находится в поле User Code и выглядит примерно так.

C# User Code

Кода там на самом деле много, но пользовательская функция всего одна: Control7_OnAction.
Итак, после того как XML и C# были выгружены во внешние файлы, считаю своим долгом загрузить их обратно. Естественно предварительно отредактировав.

В XML файле поменяем строку:

<Controls xsi:type=”ControlDefinition” ID=”5″ ControlGUID=”{0000C352-0000-0005-0008-0000836BD2D2}” DataColumnName=”8“/>

На строку:

<Controls xsi:type=”ControlDefinition” ID=”5″ ControlGUID=”{0000C352-0000-0005-0008-0000836BD2D2}” DataColumnName=”22“/>

Это говорит системе, что в данном столбце нужно выводить двадцать второе поле из таблицы-источника (поле 22 в таблице Item – это поле Unit Cost).
Но это еще не все. Теперь займемся действиями и заменим строку:

<Actions xsi:type=”ActionDefinition” ID=”7″ Name=”<Action7>” CaptionML=”ENU=Message” ControlGUID=”{0000C352-0000-0007-0008-0000836BD2D2}” RunFormMode=”Edit” Promoted=”1″ PromotedCategory=”Process” PromotedIsBig=”1″>

На строку:

<Actions xsi:type=”ActionDefinition” ID=”7″ Name=”<Action7>” CaptionML=”ENU=Message” ControlGUID=”{0000C352-0000-0007-0008-0000836BD2D2}” Image=”Delegate” RunFormMode=”Edit” Promoted=”1″ PromotedCategory=”Process” PromotedIsBig=”1″>

Мы добавили новый атрибут Image, поэтому у нашего действия изменится картинка.

Но закончим с XML, и перейдем к редактированию кода C#.
Заменим строку:

NavDialog.ALMessage(new Guid(50002, 0, 10376, 3, 8, 0, 0, 131, 107, 210, 210), ( (NavCode)(Rec.GetFieldValueSafe(1, NavType.Code)) ));

На строку:

NavDialog.ALMessage(new Guid(50000, 0, 10376, 3, 8, 0, 0, 131, 107, 210, 210), ( (NavText)(Rec.GetFieldValueSafe(3, NavType.Text)) ));

Т.е. вместо поля No должно отображаться поле Description.

Теперь загрузим обновленные файлы в соотвествующие BLOB-поля и посмотрим как будет выглядеть страница в ролеориентированном клиенте.

Item List Lite

Как можно заметить страница выглядит по-новому:
1. У кнопки Message новый рисунок.
2. В третьем поле теперь отображается Себестоимость Единицы вместо Базовой Единицы Измерения.
3. В сообщении отображается Описание товара, а не его Номер.

Главное не компилировать объект в самом Navision, иначе все изменения будут потеряны (придется загружать из файлов).
Можно приступать к созданию своей среды разработки.

Метки:



Комментариев: 1

  1. Дмитрий пишет:

    Взялся разбираться с разработкой в 2009, статьи очень в этом помогают.

    Спасибо!

Оставьте свой отзыв!