Статья: Web Services и MS Visual FoxPro Часть 4

В этой статье :
Web Service для нашего большого примера.
Ну вот и мы и добрались до самого главного - Web Service. Не буду Вас томить ожиданием, а приведу сразу весь код:
*/--------------------------------------------------------------------------/*
*
* MS VFP version..: 9.0 (так как применим новые данные совместимые с SQL Server)
* Program-ID......: WS_MES_SERVER.PRG
* Purpose.........: Непосредственно WEB Service
* Project Manager.:
* Programmer......: Sergey Chavlytko
* Start...........: 23/05/2005
* Last edited.....: 23/05/2005
*
* (С) www.sergey.co.uk 2005
*/--------------------------------------------------------------------------/*

DEFINE CLASS WS_MES_SERVER AS SESSION OLEPUBLIC

  PROCEDURE INIT && процедура, выполняемая при каждом вызове Web Service
* Вы можете писать сюда все что Вам необходимо для инициализации работы программы
* Например, глобальные переменные

  SET DELETED ON
  SET DATE DMY
  SET EXCLUSIVE OFF
  SET MULTILOCKS ON
  SET REPROCESS TO 1000
  SET STRICTDATE TO 0
  SET CENTURY ON

* явно определяем установки среды, которые будут видны во всем Web Service
* обычно эту информацию следует записывать во внешний DBF файл конфигурации
  PUBLIC gcWebSDat
  gcWebSDat='C:\ws_message\server\'

*!* If you do any work with SQL Pass-Through
*!* these settings are a good idea.
  SQLSETPROP(0,"DispLogin",3)
  SQLSETPROP(0,"DispWarnings",.F.)
  ENDPROC

*
* Процедура login в систему - принимает в качестве параметров login и password
* выдает курсор с одной строкой в виде информации о клиенте
*
  PROCEDURE login(m.lclog,m.lcpsw) AS STRING
  IF !DBUSED('DBWS')
    OPEN DATABASE (gcWebSDat+'DBWS')
  ENDIF
  lcXMLa11=-1
  lcXMLa11=sp_user_login_xml(m.lclog,m.lcpsw)
  CLOSE DATABASES ALL
  RETURN (lcXMLa11)
  ENDPROC

*
* В каждой процедуре передается снова логин, пароль
* и дополнительные параметры. В реальной жизни я их шифрую,
* причем все без исключения.
*
* В принципе, систему безопасности можно и ослабить...
*
* Данный пример показывает, как можно упростить разработку
* Web Service при выполнении однотипных операций
* кроме того такая некоторая "запутанность" приводит к повышению
* уровня безопасности.
*
  PROCEDURE message_read(m.lckey_word,m.lcUser_nick, m.lcpassword,m.lcparameter1,m.lcparameter2,;
    m.lcparameter3,m.lcparameter4,m.lcparameter5,m.lcparameter6) AS STRING
  IF !DBUSED('DBWS')
    OPEN DATABASE (gcWebSDat+'DBWS')
  ENDIF
  lcXMLa11=-1
  DO CASE
  CASE m.lckey_word='READ_MESSAGES_START' && чтение заголовков сообщений
    lcXMLa11=sp_message_read(m.lcparameter1, m.lcUser_nick, m.lcpassword, m.lcparameter2)
  CASE m.lckey_word='READ_ALL_USERS' && чтение всех пользователей
    lcXMLa11=sp_users_read_xml(m.lcUser_nick, m.lcpassword)
  CASE m.lckey_word='ADD_NEW_MESSAGE' && добавление нового сообщения
    lcXMLa11=sp_new_message_add(m.lcUser_nick, m.lcpassword,m.lcparameter1,m.lcparameter2,m.lcparameter3)
  CASE m.lckey_word='READ_THREAD_START' && чтение всех ответов на конретное сообшение
    lcXMLa11=sp_thread_read(m.lcUser_nick, m.lcpassword,m.lcparameter1)
  CASE m.lckey_word='ADD_EXISTS_MESSAGE' && добавление ответа на существующее сообщение
    lcXMLa11=sp_existed_message_add(m.lcUser_nick, m.lcpassword,m.lcparameter1,m.lcparameter2)
  CASE m.lckey_word='DELETE_THREAD' && Удаление всего потока сообщения с сервера
    lcXMLa11=sp_message_delete(m.lcUser_nick, m.lcpassword,m.lcparameter1)
  CASE m.lckey_word='DELETE_ANSWER' && Удаление одного ответа из сообщения с сервера
    lcXMLa11=sp_answer_delete(m.lcUser_nick, m.lcpassword,m.lcparameter1,m.lcparameter2)
  CASE m.lckey_word='READ_PROFILE_USERS' && Чтение профиля пользователя с сервера
    lcXMLa11=sp_users_profile_read_xml(m.lcUser_nick, m.lcpassword,m.lcparameter1)
  CASE m.lckey_word='ADD_NEW_USER' && Добавление/изменение профиля клиента
    lcXMLa11=sp_users_add_edit(m.lcUser_nick, m.lcpassword,m.lcparameter1,m.lcparameter2)

  ENDCASE
  CLOSE DATABASES ALL
  RETURN (lcXMLa11)
  ENDPROC

* это и есть наш тестовый пример
  PROCEDURE test() AS INTEGER
  RETURN (1)
  ENDPROC

ENDDEFINE
WS_MES_SERVER.PRG

Как Вы видите, ничего серьезного и таинственного. В процедуре INIT можно задавать любые установки, которые будут потом видимы всем методам внутри класса. Благодаря применению ХП в базе данных, здесь все свелось просто к вызову соответствующих ХП с параметрами. Причем параметр может быть XML файл, в котором можно спрятать довольно большую таблицу или много других параметров (тем самым обходя ограничения на количество переданных праметров). В практической жизни таблицы я вначале сохраняю в виде текстового файла с разделителями, затем этот файл вставляю в поле MEMO BINARY курсора, преобразую получившуюся таблицу с одной строкой в XML курсор и отправляю его по сети. Так на файлах размером более 5 Mb получается существенная экономия интернет-трафика и, соответственно, повышение скорости работы.

Процедуры могут вернуть только один параметр. В нашем случае это, как правило, XML файл, в котором находится наш курсор. В принципе, все довольно просто и прозрачно.
Публикация Web Service (некоторые ключевые моменты).
Мы очень надеемся,что Вы проделали предыдущий пример и научились публиковать простейший WS. Мы не изменили имя файла для нашего примера, так что основные моменты остаются прежними. Первое отличие появится при построении Multi-Thread COM server (dll) - компилятор выдаст ошибку, что не может найти некоторые файлы, например:
Одно из возможных сообщений об ошибке.
Приглядевшись повнимательней, мы поймем, что компилятор не смог найти Хранимую Процедуру. К сожалению, автору данной статьи не удалось найти способа избежания появления данных сообщений об ошибках, так что просто жмем кнопку Ignore и продолжаем работу. В итоге "допустимы" следующие "ошибки": 
Полный список ХП ненайденных компилятором.
То есть мы, по существу, получили полный список ХП нашей базы данных. В принципе, как мне посказали на форуме - можно включить нашу базу данных в проект, где находится наш WS и сообщения об ошибках исчезнут. Я этого не делал, так что у Вас есть возможность поэкспериментировать.
Теперь следующая проблема. Если после создания Web Service Вы попытаетесь запустить его, он будет блокирован IIS (Internet Information Service). Вы не сможете создать DLL (а если Вы обращались к Вашей базе данных, то она тоже остается открытой, и Вы не сможете отбразить внесенные изменения в ХП). Для решения данных проблем необходимо перезапустить Ваш IIS. Например, как показано на следующей картинке:
Перезапуск IIS.
Далее жмём OK
Подтверждаем наше решение.
Если Вы нетерпеливы, то можно нажать кнопку немедленной перезагрузки в следующем экране:
Кнопка ускорения презагрузки.
Приведенные снимки экранов актуальны для IIS 5.1 и ОС Windows XP. Для других версий продуктов они могут отличаться в ту или иную сторону. И не забудьте, что если Вы в сети, то сразу после загрузки кто-то может снова затребовать Ваш ресурс, и Вам придется повторить операцию с начала или просто остановить IIS и сделать свое дело.
Вернемся снова к нашему Web Service. Просто покажу финальный экран, где будут видны все методы создаваемого нами WS:
Список методов в нашем WS.
Как мы видим, методов три. Мы специально оставили уже известный Вам метод test. В будущем Вы сможете легко проверить, работает Ваш Web Service или нет. И где проблема - в самом WS или в правах доступа к таблицам базы данных.
Вот вроде бы и все. Web Service работает, но если мы попытаемся работать с реальными данными, Вы увидите, что не сможете ничего записать в Вашу базу данных. Причина тут простая - по умолчанию у WS нет права писать на Вашем компьютере. Далее наши объяснения будут сильно отличаться от того, где находится Ваш компьютер, и какая на нем установалена операционная система. Начнем с Windows XP на отдельно стоящей (не включенной в домен) рабочей станции. Находим папку, где у Вас WS (В нашем случае C:\ws_message\server):
Папка с нашим WS.
Нажимаем правую кнопку на папке server, из всплывающего меню выбираем Property. На этой закладке выбираем ярлык Sharing, на котором производим следующие установки (но для этого у Вас должны быть права администратора на этот компьютер):
Даем право записи нашему WS в данный директорий.

Вы уменьшаете уровень защищенности Вашего компьютера, так что смотрите сами, чтобы кто-то с негативными намерениями не испортил Вашу информацию.

Если Ваш компьютер находится в домене, то Вам необходимо дать доступ на запись к директории, где у Вас находятся данные, клиенту компьютера по имени IUSR_SERGEY04 (это операцинная система создает этого клиента по умолчанию, где IUSR_ у всех компьютров постоянно, а SERGEY04 - имя Вашей машины (у Вас оно должно быть другим)). Вы можете сменить пароль этого клиента или даже дать доступ глобальному интернет-клиенту в Вашем домене. Посмореть клиента по умолчанию для Вашего IIS можно, нажав правую клавишу мышки на  Вашем виртуальном директории и выбрав в свойствах - Directory Security:
Сморим клиента для IIS.
Если нажать клавишу Browse, то можно сменить клиента.
Вот в общем-то и все. Трудно объять необъятное, но думаю, что Ваши вопросы помогут сформировать FAQ. Скачать исходные тексты для Web Service и создания Базы данных можно отсюда (файл ws_mes_serv.zip 34 Kb).