Пример Web-интерфейса для работы с NAV 2009. Часть 1.

Р’ предыдущем выпуске был приведен СЂСЏРґ статей, рассказывающих РѕР± основах функционирования Web Services РІ Dynamics NAV. РџРѕРјРёРјРѕ РѕСЃРЅРѕРІ, были приведены несколько небольших примеров того, как можно реализовать Web Service РїРѕРґ нужды конкретной задачи. Р’ качестве клиентов выступали Windows Service Рё Win Forms, которые обращались Рє NAV…

Но чего в предыдущем выпуске (да и во всех остальных тоже) не было, так это реализации хотя бы элементарного Web Interface для NAV. Собственно, решением данной задачи мы и займемся.

Пару месяцев назад довелось РјРЅРµ участвовать РІ оживленной РґРёСЃРєСѓСЃСЃРёРё РЅР° http://mibuso.com/forum/. Суть заключалась РІ том, что автор темы РЅРµ РјРѕРі справиться СЃ некоторыми трудностями, которые возникли Сѓ него РІРѕ время реализации веб-клиента для NAV… РљРѕРіРґР° же автор того топика разрешил удаленно приконнектиться СЃ помощью TeamViewer Рє его машине Рё посмотреть  РЅР° того самого клиента, СЏ был удивлен: передо РјРЅРѕР№ был web-интерфейс классического клиента. РћРґРёРЅ РІ РѕРґРёРЅ. Дальше углубляться РЅРµ стали, РѕРЅ пооткрывал пару форм, РЅРѕ этого хватило, чтобы произвести немалое впечатление… Реализация, хотя Р±С‹ отчасти, более/менее функционального web-клиента, прежде всего, поможет РёРј обойти ограничение РїРѕ количеству конкурентных пользователей. Хотя тут тоже РЅРµ РІСЃРµ так просто… Причем РІСЃРµ – абсолютно легально…

Р?так, какие же инструменты Рё технологии пригодятся нам сегодня:

  • IIS (Internet Information Services);
  • PHP (PHP: Hypertext Preprocessor);
  • WCF (Windows Communication Foundation);
  • ASP.NET, AJAX.

Перечислено РјРЅРѕРіРѕ чего, РЅРѕ взято будет совсем понемногу РѕС‚ каждой составляющей…

Р?так, давайте представим, что РјС‹ хотим реализовать динамическую веб-страницу, которая имеет пару списочных полей, пару текстовых полей Рё пару РєРЅРѕРїРѕРє для вызова функций. Конечный ее РІРёРґ будет примерно следующим:

В picture-1.png

В левом ListBox будет отображаться список клиентов в формате [Номер];[Название]. В правой части будет отображаться список комментариев по клиенту, который активируется в левом окне. В классическом же клиенте комментарии по клиенту можно увидеть, нажав последовательно кнопки Клиент -> Комментарии:

picture-2.png

Для вывода всех клиентов на web-страницу, необходимо нажать кнопку «Get Customer». Если ввести название любого клиента в левый нижний input, в SQL-запросе будет наложен фильтр по названию клиента.

Если выделить строку с клиентом, то в правом ListBox должны отразиться все комментарии по данному клиенту. После ввода нового комментария в правом нижнем input-поле, он тут же отразится в списке всех комментариев, и, конечно, будет внесен в базу. Для вывода данных (клиентов и комментариев по ним) будем работать с базой посредством PHP-скрипта, вызываемого JavaScript’ом с web-странички. Для добавления комментариев по клиенту будем использовать web-службу, реализованную в контракте WCF (Windows Communication Foundation) службы.

Для реализации этой нехитрой функциональности нам необходимо правильно установиться IIS (можно воспользоваться Рё Apache, РєРѕРјСѓ как больше РїРѕ душе). Р?нструкцию РїРѕ установке IIS можно найти, Рє примеру, здесь: http://msdn.microsoft.com/en-us/library/ms751518.aspx.

IIS понадобится нам для того чтобы:

  • РІ нем располагалась наша динамическая страница;
  • РЅР° сервере IIS хостилась WCF-служба.

Подробнее СЃ технологией WCF можно ознакомиться РЅР° бесчисленном количестве ресурсов. РќРѕ, как РјРЅРµ кажется, РѕРґРЅРёРј РёР· наиболее продвинутых является этот (собственно, ресурс вендора). WCF рекомендую начать изучать всем, кто так или иначе хочет нормально писать web-приложения для Навижина…

Помимо IIS, необходимо, чтобы наш браузер поддерживал JavaScript. Ну и не забудем о PHP. Собственно, можем запустить онлайновый инсталлятор, который и PHP нам установит, и IIS сконфигурирует как надо: http://php.iis.net/

После установки необходимых компонентов, приступим к реализации проекта в Visual Studio. Нам необходимо выбрать проект с шаблоном «WCF Service». Разместим его на IIS-сервере, выбрав в Visual Studio последовательность действий File->New->Web Site:

picture-3.png

РџРѕ-умолчанию, создаются конфигурационный файл Web.config (содержит информацию РїРѕ конфигурации WCF-службы), файл Service.svc СЃ информацией, необходимой для хостинга службы, Р° также файлы IService.cs Рё Service.cs.. Файл IService.cs можно удалить, поскольку РѕРЅ содержит демо-пример интерфейса IService, который реализуется РІ классе Service одноименного файла…

Непосредственно к реализации службы мы пока не приступаем, поскольку нет еще web-интерфейса, который будет выступать в роли клиента по отношению к данной службе. К реализации веб-страницы мы сейчас и приступим.

Добавим новый элемент в наш проект: «AJAX Web Form». Данный элемент позволит задействовать возможность работы как с клиентским JavaScript, так и с технологией AJAX (Asynchronous Javascript and XML). AJAX нужен будет нам для того, чтобы не перегружать нашу web-страницу полностью при очередном обновлении данных, либо при очередной их выборке из базы. Вообще ASP.NET AJAX – один из наиболее популярных каркасов в построении web-приложений. Он не просто содержит развитую библиотеку клиентских классов, но и множество элементов управления.

Р?так, РІРѕС‚ как выглядит наш проект РЅР° текущем этапе:

picture-4.png

Наберем в строке браузера следующую строку: http://localhost/WCFService/AJAXWebForm4NAV.aspx

Откроется пустая страница. А пустая она потому, что мы еще не определили на ней ни одного элемента. Для того, чтобы сделать это, внесем следующий код в тело тега <form>:

<table>
В  <tr style=”height:500px;vertical-align:top;“>
В  В  <td style=”width:400px;height:400px;“>Select a customer:<br />
В  В В В  <asp:ListBox onclick=”SetMode(’Comments’);” ID=”CustomersListBox” runat=”server” Width=”100%” Height=”100%”>
В В В В В 
</asp:ListBox>
В В В В </td>
В В В В <td style=”width:400px;height:400px;“>Comments:<br />
В В В В В  <asp:ListBox ID=”CommentsByCustomerListBox” runat=”server” Width=”100%” Height=”100%”>
В В В В В 
</asp:ListBox>
В В В В </td>
В В </tr>
В В <tr style=”height:100px;vertical-align:top;“>
В В В  <td style=”width:400px;“>Enter the customer’s name:<br />
В В  В В  <asp:TextBox id=”CustomerNameTextBox” runat=”server” name=”CustomerNameTextBox” width=”95%” />
В В В В В  <input id=”GetCustomerInput” runat=”server” type=”button” value=”Get Customer” onclick=”SetMode(’Customers’);” />
В В В  </td>
В В В  <td style=”width:400px;“>Enter the comment by customer:<br />
В В В В В  <asp:TextBox id=”CustomerCommentTextBox” runat=”server” name=”CustomerCommentTextBox” width=”95%” />
В В В В В  <input id=”SetCustomerCommentInput” runat=”server” type=”button” value=”Set Comment” onclick=”SetCustomerComment();” />
В В В  </td>
В  </tr>
</table>Во-первых, мы определили основные элементы страницы. А во-вторых, подписались на события onclick в 3-х элементах их 4-х:

  • РїСЂРё активации любой строки СЃ клиентом РІ левом ListBox’e, вызывается метод SetMode СЃ текстовым параметром вЂ?Comments’. Этот метод обновляет правый ListBox: заносит РІ него информацию РїРѕ комментариям, связанным СЃ выделенным РІ левом ListBox’е клиентом;
  • РїСЂРё нажатии РєРЅРѕРїРєРё В«Get CustomerВ» срабатывает метод SetMode СЃ текстовым параметром вЂ?Customers’. Этот метод обновляет левый ListBox: заносит РІ него информацию либо РїРѕ абсолютно всем клиентам (РєРѕРіРґР° поле В«CustomerNameTextBoxВ» пустое), либо РїРѕ клиентам, название которых удовлетворяет введенному РІ поле В«CustomerNameTextBoxВ» (срабатывает SQL-запрос СЃ инструкцией LIKE);
  • РїСЂРё нажатии РєРЅРѕРїРєРё В«Set CommentВ» срабатывает процедура SetCustomerComment, связывающая СЃ выделенным клиентом введенный пользователем комментарий.

Реализация функций SetMode, и GetCustomerDB, которую она вызывает, приведена ниже:

 

m1_picture-5.png

Сперва происходит создание XMLHttpRequest объекта, который и будет использоваться нами для «общения» клиента (страницы) с PHP-скриптом. При этом перезагрузки страницы происходить не будет. Далее мы подписываемся на события, которые происходят при каждой смене статуса состояния объекта XMLHttpRequest. А затем, в зависимости от режима (хотим вывести клиентов/комментарии), отправляем запрос на сервер.

Здесь я приведу пример того PHP-скрипта, который будет выдавать клиентов/комментарии по ним, в зависимости от передаваемых в скрипт параметров:

<?phpВ header(”Content-type: text/html; charset=windows-1251″);
header(”Cache-Control: no-store, no-cache, must-revalidate”);
header(”Cache-Control: post-check=0, pre-check=0″, false);// DB & server parameters
$server = “Romul”;
$db = “Demo_Database_NAV_6_0″;
$user = “sa”;
$password = “sa”;В // connect to the NAV DB
$dbhandle = mssql_connect($server,$user,$password) or die(”Can’t connect to the $server server”);
$selecteddb = mssql_select_db($db,$dbhandle) or die(”Can’t connect to the $db database”);В if (isset($_GET[”isGetCust”]))
{
В В  // select data from the Customer table…В 
В 
$query = “select * from dbo.[CRONUS International Ltd_”.’$’.”Customer]”;
В В В  if(!empty($_GET[”customerName”]))
В В  {
В В В В В В В В В В В В В В  $where = “Name LIKE ‘”.mssql_real_escape_string($_GET[”customerName”]).”%’”;
В В В В В В В В В В В В В В  $query .= ” WHERE $where”;
В В  }В В В  // executing the query
В В  $result = mssql_query($query);
В В  if (mssql_num_rows($result) < 1)
В В В В В В В В В В В В В В  echo “No data found.”;
В В  else
В В  {
В В В В В В В В В В В В В В  $i = 0;
В В В В В В В В В В В В В В  $customers = null;
В В В В В В В В В В В В В В  while($row = mssql_fetch_array($result))
В В В В В В В В В В В В В В  {
В В В В В В В В В В В В В В В В В В В В В В В В В  $customers[$i] = $row[”No_”].”;”.$row[”Name”];
В В В В В В В В В В В В В В В В В В В В В В В В В  $i = $i + 1;
В В В В В В В В В В В В В В  }
В В В В В В В В В В В В В В  echo json_encode($customers);В // return to js-script the array of Customers using one of the function of Javascript Object Notation (JSON)
В В  }
В В  В В  unset ($_GET[”isGetCust”]);
}
elseif (isset($_GET[”isGetCommentsByCust”]))
{
В В  $query = “select * from dbo.[CRONUS International Ltd_$”.”Comment Line]”;
В В  if(!empty($_GET[”customerNo”]))
В В  {
В В В В В В В В В В В В В В  $where = “[Table Name] = 1 and No_ = ‘”.mssql_real_escape_string($_GET[”customerNo”]).”‘”;
В В В В В В В В В В В В В В  $query .= ” WHERE $where”;
В В  }
В В  В В  $result = mssql_query($query);
В В  if (mssql_num_rows($result) > 0)
В В  {
В В В В В В В В В В В В В В  $i = 0;В 
В В В В В В В В В В В В В 
$commentsByCustomer = null;
В В В В В В В В В В В В В В  while ($row = mssql_fetch_array($result))
В В В В В В В В В В В В В В  {
В В В В В В В В В В В В В В В В В В В В В В В В В  $commentsByCustomer[$i] = $row[”Comment”];
В В В В В В В В В В В В В В В В В В В В В В В В В  $i = $i + 1;
В В В В В В В В В В В В В В  }
В В В В В В В В В В В В В В  echo json_encode($commentsByCustomer);
В В  }
В В  В В  unset ($_GET[”customerNo”]);
}// close connection…
mssql_close($dbhandle);В // analogue of mysql_real_escape_string
function mssql_real_escape_string($string_to_escape)
{
В В  $replaced_string = str_replace(”‘”,”””,$string_to_escape);
В В  return $replaced_string;
}В ?>В 

Во-первых, мы отключаем кэширование, дабы получать каждый раз уже обновленные данные, а не старые закэшированные. Во-вторых, пытаемся приконнектиться к серверу и базе. Далее:

  • если РІ момент обращения Рє серверу была инициализирована переменная isGetCust, выбираем данные РїРѕ клиенту/клиентам (если фильтр наложен РЅРµ был). Если количество возвращаемых РёР· базы данных строк (информации РїРѕ клиентам) > 0, тогда обрабатываем полученный кортеж данных, используя для этого функцию mssql_fetch_array. После чего «упаковываем» полученный массив данных $Customer РІ массив текстового формата обмена данными JSON (JavaScript Object Notation). Такой массив очень просто обработать СЃ использованием JavaScript, РєРѕРіРґР° настанет время парсить полученный РѕС‚ сервера ответ;
  • если РІ момент обращения Рє серверу была инициализирована переменная isGetCommentsByCust, то выбираем комментарии, связанные СЃ этим клиентом Рё так же передаем браузеру результат РІ РІРёРґРµ JSON-массива.
  • закрываем соединение СЃ сервером

Функция mssql_real_escape_string, приведенная в самом конце скрипта, служит для экранирования и является аналогом встроенной в php функции mysql_real_escape_string (для работы с MySQL).Когда приходит ответ от сервера, необходимо обработать массив полученной информации, либо ошибку. Для обработки данных на стороне клиента используется функция HandleResponseFromDB:

m1_picture-6.png

Когда данные загружены с сервера (readyState == 4) и получен безошибочный ответ от сервера (200), происходит очистка обоих ListBox’ов:

m1_picture-7.png
После очистки ListBox’ов происходит распарсивание полученных ответов от сервера и заполнение нужного ListBox’a.
Ниже представлен результат на динамической странице:

m1_picture-8.png

 

А это – стандартный интерфейс классического клиента:
m1_picture-9.png

Метки: ,



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

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

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

  2. Orwell пишет:

    Добрый день, Дмитрий.
    Р?Р·РІРёРЅСЏСЋСЃСЊ Р·Р° РїРѕР·РґРЅРёР№ ответ: давно РЅРµ заходил РЅР° сайт.
    Если что-то РЅРµ получается, то РІ первую очередь надо СЃ разбираться СЃ правами/аккаунтами/именем базы Рё прочими вещами, которые так или иначе РјРѕРіСѓС‚ влиять РЅР° работу СЃ сервисами Рё СЃ БД Навижина…
    К тому же, если Вы совсем новичек в web-технологиях, рекомендую все же сперва разобраться с основами IIS, PHP, ASP.NET, AJAX. А уже после этого приступать к реализации этого немудренного примера.
    Я отправил на Вашу почту архив со студийным проектом. Если что-то будет непонятно - задавайте вопросы.

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