Статья: web services и ms visual foxpro Часть 1 · web viewweb services и ms visual...

68
Статья: Web Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта статья. Что такое Web Services. Немного об XML и “заточки под него VFP”. Простой пример получения данных посредством WS из Интернета. Для чего написана эта статья. В последнее время все чаще можно услышать разговоры о том, что FoxPro - это устаревшая технология 80-х, что программисты, которые остались верны данной среде разработки "отстали от жизни", что у них "нет будущего" и, вообще, "они ничего не понимают в развитии IT индустрии"... Прочитав эту статью, Вы научитесь применять FoxPro в глобальных масштабах всего мира. Для Вас будет абсолютно без разницы, для чего писать приложения - для маленькой задачи на одном компьютере, для целого предприятия, работающего в среде Интранет, для крупной компании, спрятавшей своих клиентов за навороченными системами защиты "firewall", или для ее филиалов, разбросанных по всему миру, и имеющих разнородный парк серверов, на которых крутятся разношерстные операционные системы от Windows 2000, 2003 до Unix. Web Services размывают наши представления о различиях между файл - серверными и клиент - серверными приложениямию. Теперь Вы можете передавать между компьютерами только минимально необходимый набор информации, применяя хранимые процедуры и транзакции на удаленном сервере данных, тем самым лишая многих критиков FoxPro основных аргументов против применения данной среды в современных надежных и легко масштабируемых приложениях (так как в этом случае Вам не надо ничего будет менять в клиентском приложении - только изменить немного WS). Причем, Вы неожиданно откроете для себя, что такие феноменальные возможности появились у старого и доброго FoxPro еще много лет назад в 7 версии, намного опережая продвинутые продукты конкурентов и даже многие продукты самого Microsoft (например, SQL Server 2000). Проблема была только в Вас самих - Вы этим не пользовались. Мы очень надеемся, что данная статья Вам поможет пересмотреть Ваши взгляды на Ваш привычный процесс разработки приложений, дав толчок к внедрению новых технологий у Ваших клиентов и, в конечном итоге, к upgrade Ваших skills. В данной публикации мы попытаемся "объять необъятное", разумеется, с Вашей помощью в виде отзывов, которые помогут улучшить понимание данного материала и сделать его более понятным для тех, кто

Upload: others

Post on 06-Jun-2020

7 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

Статья: Web Services и MS Visual FoxPro Часть 1В этой статье :

Для чего написана эта статья. Что такое Web Services. Немного об XML и “заточки под него VFP”. Простой пример получения данных посредством WS из Интернета.

Для чего написана эта статья.В последнее время все чаще можно услышать разговоры о том, что FoxPro - это устаревшая технология 80-х, что программисты, которые остались верны данной среде разработки "отстали от жизни", что у них "нет будущего" и, вообще, "они ничего не понимают в развитии IT индустрии"...  Прочитав эту статью, Вы научитесь применять FoxPro в глобальных масштабах всего мира. Для Вас будет абсолютно без разницы, для чего писать приложения - для маленькой задачи на одном компьютере, для целого предприятия, работающего в среде Интранет,  для  крупной компании,  спрятавшей своих клиентов за навороченными системами защиты "firewall", или для ее филиалов, разбросанных по всему миру, и имеющих разнородный парк серверов, на которых крутятся разношерстные операционные системы от Windows 2000, 2003 до Unix. Web Services размывают наши представления о различиях между файл - серверными и клиент - серверными приложениямию. Теперь Вы можете передавать между компьютерами только минимально необходимый набор информации, применяя хранимые процедуры и транзакции на удаленном сервере данных, тем самым лишая многих критиков FoxPro основных аргументов против применения данной среды в современных надежных и легко масштабируемых приложениях (так как в этом случае Вам не надо ничего будет менять в клиентском приложении - только изменить немного WS).

Причем, Вы неожиданно откроете для себя, что такие феноменальные возможности появились у старого и доброго FoxPro еще много лет назад в 7 версии, намного опережая продвинутые продукты конкурентов и даже многие продукты самого Microsoft (например, SQL Server 2000). Проблема была только в Вас самих - Вы этим не пользовались. Мы очень надеемся, что данная статья Вам поможет пересмотреть Ваши взгляды на Ваш привычный процесс разработки приложений, дав толчок к внедрению новых технологий у Ваших клиентов и, в конечном итоге, к upgrade Ваших skills. В данной публикации мы попытаемся "объять необъятное", разумеется, с Вашей помощью в виде отзывов, которые помогут улучшить понимание данного материала и сделать его более понятным для тех, кто только начинает свой путь по нелегкой тропе к вершинам программистского мастерства.

Page 2: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

Что такое Web Services.В начале моей нелегкой жизни профессионального программиста   клиенты часто просили меня рассказать, как работает написанная мной программа. Мои объяснения сводились примерно к следующему: “Вы нажимаете кнопку "вывести на экран справочник товара", и компьютер посылает запрос к серверу в виде строки, в которой указывает то, что Вам надо. Далее сервер обрабатывает Ваш результат, формирует ответную строку и посылает ее назад. Моя программа принимает ответ и показывает Вам в удобочитаемом виде этот самый справочник...” Все были довольны: клиент тем, что понял, а я, что удалось ему объяснить.

Только через несколько лет я обнаружил, что это была голая ложь по отношению к файл – серверу. Даваемое мной описание подходит больше под КС (клиент-серверное приложение), а в идеале, на приложение, где источником данных является Web Service. Так что же все-таки это непонятное импортное словосочетание означает на самом деле? Цель моей скромной статьи - приоткрыть завесу тайны и мистики над этой технологией, которой пророчат большое будущее как Microsoft, так и их конкуренты.

С технической точки зрения Web Services (сокращенно WS) - это DLL, установленная на Вашем Web Server, которая может быть вызвана другими компьютерами, находящимися как во внутренней сети Intranet, так и во внешней сети Internet. Методы в этой DLL могут делать то же самое, что и COM сервер. Если объяснять простыми словами, то Web Service  просто очень маленькая программка, которая прослушивает определенный порт в IIS (Internet Information Server, или в простонародии “Сервер WEB”). Как мы, наверное, с Вами знаем, каждый WEB сервер имеет адрес IP (например,  у локального 127.0.0.1) и порт (для Вашего WEB Server по умолчанию 80 ). Когда мы с Вами набираем, например, http://www.sergey.co.uk/ , то наш Browser (программа, с помощью которой Вы “гуляете по Интернету”) посылает Ваш запрос к DNS серверу, который говорит, что для данного адреса будет следуюший IP -  62.105.65.69,  и Вы направляетесь прямо туда, где находится мой сайт. Если теперь указать имя конкретного файла, имеющего расширение .WSDL, то IIS поймет, что запрос предназначен для WS, разбудит его, и последний начнет обработку нашего запроса, как самая обычная программа, запущенная удаленно – то есть на чужом удаленном (remote) компьютере. Передав параметры WS, Вы можете запросить только интересующую Вас информацию, например, курсы валют на определенную дату, список книг в библиотеке по автору, список неоплаченных счетов... Вот собственно и все. Просто, как "Автомат Калашникова".

Немного об XML и “заточки под него VFP”.

Page 3: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

Итак, если мы немного знакомы с Интернет - технологиями, то обмен данными там ведется с помощью протокола HTTP, который, как известно, ничего кроме символьных строк не понимает... Как же "выкрутиться" из данной ситуации, ведь нам надо передавать цифры, спецсимволы и даже картинки с двоичными данными? Для этого люди придумали XML (Extensible Markup Language). Для тех, кто любит изучать вещи досконально, советую посетить страничку http://www.w3.org/XML/ , где можно узнать последние новости об этом языке. Мне, как программисту баз данных, достаточно знать только то, что каждое выражение (как и в случае c HTML) окружено тэгами, причем один должен быть открывающим, а второй обязательно должен закрывать выражение. Рассмотрим простой пример в FoxPro, в котором полная поддержка XML появилась еще в 7 версии (просто выделяете данный текст программы и коприруете его в открытое окно редактора FoxPro):

* создаем простую таблицу

* не забыв при этом в директории проекта иметь файл config.fpw

* где есть строка: codepage=1251

* в этом случае все создаваемые нами файлы будут иметь

* корректную кодовую страницу для работы с русским языком

SET SAFETY OFF

CREATE TABLE TESTXML.DBF FREE (text1 c(40), number1 N(4), memo1 M)

* вносим несколько значений

INSERT INTO TESTXML (text1,number1,memo1) VALUES ;

('Первая строка', 1233,'Строка в Memo поле первая'+CHR(13)+CHR(10)+;

'Вот и вторая строка в Memo')

INSERT INTO TESTXML (text1,number1,memo1) VALUES ;

('Еще одна строка', 1963,'FoxPro отличает от других средства разработки'+CHR(13)+CHR(10)+;

'приложений глубокая продуманность языка для реальной жизни.')

*

* создаем файл XML из нашей таблицы

* думаю, что описание команды CURSORTOXML Вы сможете прочитать в Help

* Остановлюсь только на параметрах, примененных мною

* "TESTXML" - имя открытой таблицы

* "myXMLfile.xml" - имя файла, в который мы хотим записать полученный результат

* 1 - создать "Element-centric XML" в этом случае получаем "правильный" XML файл

Page 4: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

* +8 - обернуть Memo поле в CDATA - это значит, что можно передавать и двоичные значения

* +16 - использовать кодовую страницу курсора (в нашем случае 1251 - Russian Windows)

* +512 - вывести результат в файл

* 0 - берем все записи

* "1" - схема данных должна быть встроена в файл. То есть как бы словарь данных

* передается вместе с данными и в месте приема мы их правильно расшифровываем.

CURSORTOXML("TESTXML","myXMLfile.xml",1,8+16+512,0,"1")

* теперь просмотрим полученный файл

MODIFY FILE ("myXMLfile.xml")

* почистим за собой

CLOSE DATABASES

DELETE FILE TESTXML.DBF

DELETE FILE TESTXML.FPT

DELETE FILE myXMLfile.XML

example01.prg В результате работы программы получаем следующий файл, который Вы должны увидеть на своих экранах:

<?xml version = "1.0" encoding="Windows-1251" standalone="yes"?><VFPData> <xsd:schema id="VFPData" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:element name="VFPData" msdata:IsDataSet="true"> <xsd:complexType> <xsd:choice maxOccurs="unbounded"> <xsd:element name="testxml" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="text1"> <xsd:simpleType> <xsd:restriction base="xsd:string"> <xsd:maxLength value="40"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="number1"> <xsd:simpleType> <xsd:restriction base="xsd:decimal"> <xsd:totalDigits value="4"/>

Page 5: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

<xsd:fractionDigits value="0"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="memo1"> <xsd:simpleType> <xsd:restriction base="xsd:string"> <xsd:maxLength value="2147483647"/> </xsd:restriction> </xsd:simpleType> </xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:choice> <xsd:anyAttribute namespace="http://www.w3.org/XML/1998/namespace" processContents="lax"/> </xsd:complexType> </xsd:element> </xsd:schema> <testxml> <text1>Первая строка</text1> <number1>1233</number1> <memo1><![CDATA[Строка в Memo поле перваяВот и вторая строка в Memo]]></memo1> </testxml> <testxml> <text1>Еще одна строка</text1> <number1>1963</number1> <memo1><![CDATA[FoxPro отличает от других средств разработкиприложений глубокая продуманность языка для реальной жизни.]]></memo1> </testxml></VFPData>

Полученный результат грубо можно разбить на три части. В первой части (строке) идет объяснение, что это такое. Из всего этого нас интересует только encoding="Windows-1251", что собственно говорит о том, что мы правильно получили кодировку русского языка, и при приеме информации у нас не должно возникнуть проблем.

Во второй части идет описание формата данных. Можно очень грубо провести аналогию с заголовком таблиц DBF самого Visual FoxPro. Типы данных могут немного отличаться от привычных нам, так, например, для поля Memo - это все тот же string, но с очень большой длиной. Одно из преимуществ формата XML эксперты называют "human readable" - то есть возможность человека читать его  и понимать. Я очень надеюсь, что Вы принадлежите к человечеству и, соответственно, сможете понять, что там есть.

Третья часть, собственно, данные. Они будут зависеть от того, что Вы туда включили. В общем-то ничего сложного, я только хочу обратить

Page 6: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

внимание на загадочные буквы CDATA вокруг Memo полей. FoxPro позволяет зашифровывать данные на лету в формат base64,  который позволяет "оборачивать" двоичные файлы и передавать их в виде все тех же привычных для HTTP символов. По примерно такому же принципу мы передаем в электронной почте всевозможные картинки, музыку и даже видео.

Совсем не плохо для практически всего одной команды FoxPro!Простой пример получения данных посредством WS из

Интернета.Давайте теперь, наконец, сделаем что-то практически, что - то "крутое" и глобальное. Для следующего примера Вам понадобится связь с внешним миром, то есть Internet. Подойдет даже очень медленное модемное соединение. Усложним пример тем, что источником данных будет MS SQL Server, а Web Services будут построены на основе любимого и  революционного  детища компании Microsoft - ASP.NET (если иметь в виду некоторые принципы, заложенные в  основу ASP.NET, как, например, создание предкомпилированного кода, то эта возможность была уже применена в FoxBase 20 лет назад). То есть данный пример покажет истинную независимость Вас, как разработчика, от среды.

Итак, вот код, который Вам предлагается скопировать в окно редактора FoxPro и запустить:

************ пример получения новостей с сайта www.sergey.co.uk***********SET TALK OFF* создаем объект на основе пакета SOAP 3.0 o=CREATEOBJECT("MSSoap.SoapClient30")* соединяемся с удаленным источником данных* в качестве параметра стандартного метода MSSoapInit задается URLo.MSSoapInit("http://www.sergey.co.uk/WebModules/NewsManaer/Headlines.asmx?WSDL")* вызываем функцию данного Web Service как самую обычную функцию FoxPro* и не важно, что объект расположен от Вас за тысячи километров* Данная функция запрашивет заголовки новостей*o.getheadlines(1)loexception=NULL && устанавливаем объект, в котором будем отлавливать ошибкиtt=''* применяем конструкцию TRY..CATCH чтобы возможные проблемы не повлияли на наше* приложение. В принципе все можно было "упрятать" в эту конструкциюTRY tt=o.getheadlines(1)CATCH TO loexception && если будет ошибка, то программа нам ее распечатает ? loexception.MESSAGE ? loexception.ERRORNOENDTRY

Page 7: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

*? tt && если убрать здесь комментарий то на экране Вы увидите в случае успеха тип (Object)

IF ISNULL(loexception) && если не было ошибок, то продолжим lcXML=tt.ITEM(0).parentnode.XML && * ? lcXML && если убрать здесь комментарий то на экране Вы увидите принятый Вами XML файл* STRTOFILE(lcXML,'aaa.xml') && можно записать XML в файл на диск* для дальнейшей работы создаем XML Adapter LOCAL oXA AS XMLADAPTER oXA = CREATEOBJECT("XMLAdapter")* загружаем полученную информацию в созданный адаптер oXA.LOADXML(lcXML,.F.,.T.) IF USED('NEWS') USE IN NEWS ENDIF* создаем таблицу из адаптера с названием NEWS oXA.TABLES[1].TOCURSOR(.F.,"NEWS") BROWSE && смотрим, что получили

ENDIF* как обычно чистим за собойRELEASE o

example02.prg Программа собственно выполняет простую функию - запрашивает данные из удаленного источника и представляет в привычном для нас виде - в виде таблицы, с которой нам, программистам, уже можно делать все, что пожелаем. Комментарии объясняют для чего нам нужны основные операторы. Нами применены некоторые новые конструкции, но думаю, что они у Вас не вызовут проблем с пониманием. Если же нет, то пишите - поговорим о них более подробно .

В результате работы программы получим следующую "картинку":

Обращу Ваше внимание только на одну деталь: все символьные поля имеют тип Memo. Это связано с тем, что в ASP.NET WS надо как и в SOAP указывать обязательность передачи схемы данных внутри XML файла. Нами этого не было сделано, и FoxPro по умолчанию поставил для строковой переменной максимально возможную длину. Решить эту проблему можно двумя путями: попросить разработчиков Web Servise включать схему в XML файл, или если это невозможно (что, как

Page 8: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

правило, бывает в нашей жизни), то поработать немного самим и изменить структуру полученной таблицы в месте приема. Есть еще вариант с внешним XSD файлом, но я предлагаю опустить его, чтобы не усложнять нашу и без того сложную жизнь.Под влиянием общественности родился еще один пример, который может даже носить некоторый практический характер - получение курсов валют, публекуемых Центральным Банком России. Пример очень похож на предыдущий, так что копируйте и запускайте:

************ пример получения курса валют ЦБ РФ с сайта http://web.cbr.ru/***********SET TALK OFF* создаем объект на основе пакета SOAP 3.0o=CREATEOBJECT("MSSoap.SoapClient30")* соединяемся с удаленным источником данных* в качестве параметра стандартного метода MSSoapInit задается URLo.MSSoapInit("http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx?WSDL")* вызываем функцию данного Web Service как самую обычную функцию FoxPro* Данная функция запрашивет курсы валют как DataSet*o.DailyInfo()loexception=NULL && устанавливаем объект, в котором будем отлавливать ошибкиtt=''* применяем конструкцию TRY..CATCH чтобы возможные проблемы не повлияли на наше* приложение. В принципе все можно было "упрятать" в эту конструкциюTRY tt=o.GetCursOnDate(DATE()) && параметр - текущая дата date()CATCH TO loexception && если будет ошибка, то программа нам ее распечатает ? loexception.MESSAGE ? loexception.ERRORNOENDTRY

*? tt && если убрать здесь комментарий то на экране Вы увидите в случае успеха тип (Object)

IF ISNULL(loexception) && если не было ошибок, то продолжим lcXML=tt.ITEM(0).parentnode.XML &&* ? lcXML && если убрать здесь комментарий то на экране Вы увидите принятый Вами XML файл* STRTOFILE(lcXML,'aaa.xml') && можно записать XML в файл на диск* для дальнейшей работы создаем XML Adapter LOCAL oXA AS XMLADAPTER oXA = CREATEOBJECT("XMLAdapter")* загружаем полученную информацию в созданный адаптер oXA.LOADXML(lcXML,.F.,.T.) IF USED('CURS') USE IN CURS ENDIF* создаем таблицу из адаптера с названием CURS oXA.TABLES[1].TOCURSOR(.F.,"CURS")* немного поработаем над полученной таблицей для красоты

Page 9: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

* к сожалению в 8 версии неправильно работает команда ALTER TABLE* по этому применим дополнительный SELECT IF VERSION(5)=800 SELECT SPACE(30) AS VNAME, 0000.0 AS VNOM ,000.0000 AS VCURS , SPACE(3) AS VCHCODE ; FROM CURS WHERE 2=1 ; INTO CURSOR NEWCURS NOFILTER ; UNION ALL ; SELECT MLINE(VNAME,1), VNOM,VCURS , MLINE(VCHCODE,1) ; FROM CURS ELSE ALTER TABLE CURS ALTER COLUMN VNAME C(30) ALTER TABLE CURS ALTER COLUMN VCHCODE C(3) ALTER TABLE CURS ALTER COLUMN VNOM N(5,2) ALTER TABLE CURS ALTER COLUMN VCURS N(8,4) ENDIF

BROWSE && смотрим, что получили

ENDIF* как обычно чистим за собойRELEASE oCLOSE DATABASES

example03.prg Результат работы показан на нижеследующем рисунке (не плохой результат за пару минут работы):

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

Page 10: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

возможные проблемы...

Page 11: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

Статья: Web Services и MS Visual FoxPro Часть 2В этой статье :

Новые методы разработки приложений. Проблема. Дизайн. Создание базы данных.

Новые методы разработки приложений.Приступим к созданию более сложного примера, сделав который Вы получите необходимые навыки для применения технологии в повседневной жизни и не только. Мы постараемся рассказать Вам, как рекомендует Microsoft создавать приложения с нуля, условно разбив этот путь на три основных части:

1) Идентифицировать проблему (или поставить задачи и найти ответы на вопросы: “ Что мы хотим сделать и что должно в итоге получиться?”, “Какие ограничения или другие условия влияют на проект?”) 2) Сделать основной дизайн (решить какие функции и возможности мы должны будем разработать в системе, чтобы решить стоящую перед нами задачу). Понять в общем как система будет работать, не вдаваясь в излишние детали. 3) Создать наше рабочее приложение (написать код и выполнить другие виды работ, которые позволят сделать наш проект рабочим).

Кроме того, в основе нашего приложения будет лежать идея многослойности (n-tier): слой базы данных, своеобразный слой бизнес – логики (эту роль будет играть Service) и презентационный слой (собственно клиентская часть – то что увидят наши клиенты). Идея, лежащая в основе многослойных приложений, проста - каждый слой можно разрабатывать и модернизировать в будущем по отдельности. Из набивших уже "оскомину" на ум сразу приходит пример - заменить базу данных FoxPro на базу данных MS SQL Server... Это, наверное, самый популярный пример, так как зарплата программистов со знанием этих SQL серверов почему-то намного выше нашей, хотя работать с последним намного легче, чем с родными базами FoxPro. Странно все это, куда катится наш мир?

К недостаткам данного подхода необходимо отнести его затратность: чтобы внести изменения в программу, надо их внести в несколько мест. Так, например, для этого сайта (да, этот сайт разработан как обычная программа ASP.NET и подхода n-tire)  www.sergey.co.uk если я захочу изменить, например,  форум , я должен буду внести измения в базу данных, хранимые процедуры, слой работы с данными, бизнес-слой и , наконец, в презентационный слой. Что и говорить, кошмары современного метода разработки приложений, или добро пожаловать в мир, где все борются с безработицей подобным странным образом.

Проблема.

Page 12: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

Главная и основная задача - создать приложение, которое бы послужило базой для дальнейшей самостоятельной работы программиста FoxPro. Отсюда вытекают остальные проблемы: создать систему обмена сообщений внутри фирмы возможность ведения частных и приватных диалогов наличие специальных администраторов совмещенная экранная форма в приложении – для администратора и клиента (у администратора добавляются по мере необходимости дополнительные объекты управления) стандартный набор функций клиента:

1. регистрация (для простоты пароли будем хранить в открытом виде)

2. публиковать свои сообщения: всем (ALL) или определенному лицу (выбор из списка – в качестве параметра передовать на сервер начальные буквы User_nick)

3. отвечать на общие и приватные сообщения 4. вся необходимая информация о других клиентах будет

предоставлена в Grid

стандартный набор функций администратора: 1. добавлять пользователей и изменять их профайлы 2. удалять и редактировать любые сообщения 3. блокировать пользователей

4. наличие на форме специального фильтра, ограничивающего период запрашиваемых с сервера сообщений

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

В этом направлении все сильно запущено, но все-таки воспользуемся привычным для западного человека графическим изображением модели базы данных, применив для этого ERM диаграмму и условно-бесплатный редактор QSEE Superlight. В общем-то ничего сложного для своего примера мы брать и не собирались:

Page 13: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

Как мы видим из приведенной диаграммы, у нас будет три сущности (entity), связанные соотношениями (relationships) один ко многим. Имена атрибутов и их тип видны на рисунке. Далее, как любят показывать в рекламе, нажимается кнопка и генерируется код создания базы данных. Но не все так просто - этот код не всегда именно то, что нам надо, и приходится, как правило, довольно много потом исправлять руками. Да и наша мысль не стоит на месте. Изменения легче внести руками в готовую базу, чем рисовать это в ERM, а потом снова генерировать, исправлять... Короче, замкнутый круг на любителя. Для меня, как практика, эти диаграммы являются хорошим подспорьем для начальных бесед с клиентом. Обилие непонятных слов и картинки, как правило, производят на него неизгладимые впечатления, парализуют его мозг и позволяют легче  выбивать из него деньги (может поэтому специалисты Oracle, DB2 "гребут деньги лопатой" за гораздо меньший труд, чем программисты FoxPro, что умеют "замутить" подобным образом мозги заказчику).Для простоты повторения мы рекомендуем Вам создать аналогичную структуру директориев, как и в нашем проекте. Для серверной части, например: C:\WS_MESSAGE\SERVER\По причинам указанным выше (то есть как это принято у "серьезных админов" баз данных) приведу создание таблиц нашей базы данных в коде, запустив который Вы создадите требуемую базу данных и заполните ее некоторыми начальными значениями. Код прозрачный, так что копируете и вставляете в окно редактора программ FoxPro:

*/--------------------------------------------------------------------------/*

*

* MS VFP version..: 9.0 (так как применим новые данные совместимые с SQL Server)

* Program-ID......: DB_CREATE.PRG

Page 14: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

* Purpose.........: Создание базы данных для проекта обмена сообщениями внутри

* компании. Данная база данных должна находится в дирректории

* где Ваш Web Service (это сделано только для простоты

* понимания данного проекта)

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 22/05/2005

* Last edited.....: 07/06/2005

*

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

SET SAFETY OFF

CLOSE DATABASES ALL

PUBLIC m.pcpath

m.pcpath='C:\WS_MESSAGE\SERVER\'

* Так-как у нас SET SAFETY OFF

* предыдущая база будет удалена без предупреждения

IF FILE(m.pcpath+'\DBWS.DBC')

DELETE DATABASE (m.pcpath+'DBWS') DELETETABLES

ENDIF

* собственно создаем базу данных

CREATE DATABASE (m.pcpath+'DBWS')

CREATE TABLE m.pcpath+'USERS' CODEPAGE=1251( ;

User_ID INTEGER NOT NULL AUTOINC NEXTVALUE 1 STEP 1 PRIMARY KEY, ;

User_nick CHARACTER(10) NOT NULL, ;

PASSWORD CHARACTER(10) NOT NULL, ;

email VARCHAR(40), ;

city VARCHAR(30), ;

admin NUMERIC(1,0), ;

isblocked NUMERIC(1,0), ;

register T NOT NULL, ;

lastvisit T ;

)

* В нижеследующей таблице устанавливаем постоянные соотношения

* один ко многим с таблицей User

* хотя, в принципе, они нам и не нужны

Page 15: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

CREATE TABLE m.pcpath+'Mes_Header' CODEPAGE=1251( ;

Mes_ID INTEGER NOT NULL AUTOINC NEXTVALUE 1 STEP 1 PRIMARY KEY , ;

User_from INTEGER NOT NULL REFERENCES USERS TAG User_ID, ;

User_to INTEGER NOT NULL REFERENCES USERS TAG User_ID, ;

WASUPDATED T NOT NULL, ;

TITLE VARCHAR(100), ;

published T NOT NULL ;

)

INDEX on TTOD(WASUPDATED) TAG WASUPDATED ADDITIVE

* здесь устанавливаем постоянное соотношение

* один ко многим с таблицей Mes_Header

* применение типа Blob для Message устраняет много проблем в будущем

* при передаче данных

CREATE TABLE m.pcpath+'Mes_body' CODEPAGE=1251( ;

Reply_ID INTEGER NOT NULL AUTOINC NEXTVALUE 1 STEP 1 PRIMARY KEY, ;

Mes_ID INTEGER NOT NULL REFERENCES Mes_Header TAG Mes_ID, ;

User_from INTEGER NOT NULL REFERENCES USERS TAG User_ID, ;

MESSAGE W, ;

published T ;

)

* добавим сразу несколько необходимых записей

* Пользователь ALL (или вроде как код для широковещательного сообщения

* очень важно ввести его первой записью, чтобы код был равен 1)

* пароль выбираем случайным образом, чтобы никто не писал от его имени

INSERT INTO (m.pcpath+'USERS') (User_nick, PASSWORD,admin ,register , lastvisit ) ;

VALUES;

('ALL',SYS(2015),0,DATETIME(),DATETIME())

* администратора (для реальной системы рекомендуется сменить пароль)

INSERT INTO (m.pcpath+'USERS') (User_nick, PASSWORD,admin ,register , lastvisit ) ;

VALUES;

('admin','admin',1,DATETIME(),DATETIME())

* добавляем просто пользователя для тестирования

* здесь можете добавить себя

INSERT INTO (m.pcpath+'USERS') (User_nick, PASSWORD,admin ,register , lastvisit ) ;

VALUES;

('sergey','sergey',1,DATETIME(),DATETIME())

Page 16: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

* теперь добавим тестовое сообщение

INSERT INTO (m.pcpath+'Mes_Header') (User_from , User_to, WASUPDATED, TITLE, published) ;

VALUES ;

(2,1,DATETIME(),'Добро пожаловать в систему обмена сообщениями', DATETIME())

INSERT INTO (m.pcpath+'Mes_body') (Mes_ID,User_from ,MESSAGE,published ) ;

VALUES ;

(1,2,'Собственно поздравление.'+CHR(13)+'Надеемся, что все будет работать.', DATETIME())

* покажем, что у нас получилось

*DISPLAY TABLES

*DISPLAY DATABASE

* чистим за собой

CLOSE DATABASES

DB_CREATE.PRG Как мы видим, ничего сложного. Только пара нюансов - использование явного указания кодовой страницы и применение новго типа данных Blob. К сожалению, они доступны только начиная с версии VFP 9.0.

Далее создаем хранимые процедуры - "рабочие лошадки" нашего приложения. Существует мнение, что работать с базами данных следует только через хранимые процедуры. В принципе, хороший похдод, тем более, что все изменения в структуре Ваших данных и даже смену СУБД можно производить без смены клиента. Еще одно удобство - это ориентированность на наше WEB приложение (простота и прозрачность): клиент послал запрос в виде параметров хранимой процедуры, а в ответ получил результат. Все просто и надежно. Думаю, начав подобным образом разрабатывать приложения, Вы выбьете почву из под противников FoxPro, ибо они используют аналогичный подход и очень этим гордятся.

Все хранимые процедуры начинаются с SP (это перевод на английский ХП - Stored Procedures). Далее в названии используется английское наименование функции (для больших задач рекомендуется после SP использовать имя модуля, а затем название выполняемой функции). Теперь небольшое лирическое отступление об использовании английского языка. В принципе, можно использовать и русский, но столкнувшись с некоторыми проблемами совместимости, я пришел к выводу - использовать все-таки английский. Это хорошая практика, так как неизвестно, куда Вас закинет судьба работать завтра - может в ОАЭ, где никто не говорит по-русски, но смогут понять Ваш код на английском.

Приведу текст всех Хранимых Процедур:

*/--------------------------------------------------------------------------/*

Page 17: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

* Текст всех ХП находится в sp_procedures.txt

* Для создания всех ХП из текстового файла запустите Create_SP.PRG

*/--------------------------------------------------------------------------/*

*/--------------------------------------------------------------------------/*

*

* MS VFP version..: 9.0

* Program-ID......: sp_chk_admin.PRG

* Purpose.........: Проверка на наличие прав администратора по user_id

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 22/05/2005

* Last edited.....: 22/05/2005

*

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

PROCEDURE sp_chk_admin

PARAMETERS m.lcuser_id

SET DELETED ON

PRIVATE m.lnreturn_parameter

m.lnreturn_parameter=-1

IF m.lcuser_id>0

SELECT admin FROM USERS WHERE User_ID=m.lcuser_id INTO CURSOR user_exists

IF user_exists.admin >0

m.lnreturn_parameter=user_exists.admin

ENDIF

ENDIF

IF USED('USERS')

USE IN USERS

ENDIF

IF USED('USER_EXISTS')

USE IN user_exists

ENDIF

RETURN m.lnreturn_parameter

*/--------------------------------------------------------------------------/*

Page 18: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

*

* MS VFP version..: 9.0

* Program-ID......: sp_message_read.PRG

* Purpose.........: Чтение заголовков сообщений с сервера

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 22/05/2005

* Last edited.....: 22/05/2005

*

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

PROCEDURE sp_message_read

PARAMETERS m.lddate, m.lcUser_nick, m.lcpassword, m.lndays_show

SET DELETED ON

PRIVATE m.lnuser_id, m.lnadmin, lcXML

STORE 0 TO m.lnadmin, m.lnuser_id

m.lnuser_id=sp_user_login_id(m.lcUser_nick, m.lcpassword)

lcXML=-1 && в случае неуспеха ответ в числовом виде

IF m.lnuser_id>0

m.lnadmin=sp_chk_admin(m.lnuser_id)

IF m.lnadmin>0 && это администратор, значит есть доступ ко всем сообщениям

SELECT Mes_Header.*,User_nick, city FROM Mes_Header ;

LEFT OUTER JOIN USERS ON Mes_Header.User_from=USERS.User_ID ;

WHERE TTOD(Mes_Header.WASUPDATED) >= ;

DATE(YEAR(m.lddate),MONTH(m.lddate),DAY(m.lddate)) - m.lndays_show ;

INTO CURSOR CUR_TEMP &&

ELSE && обычный пользователь

SELECT Mes_Header.*,User_nick, city FROM Mes_Header ;

LEFT OUTER JOIN USERS ON Mes_Header.User_from=USERS.User_ID ;

WHERE (Mes_Header.User_to=1 OR Mes_Header.User_to=m.lnuser_id or ;

Mes_Header.User_from=m.lnuser_id) AND ;

TTOD(Mes_Header.WASUPDATED) >= ;

DATE(YEAR(m.lddate),MONTH(m.lddate),DAY(m.lddate)) - m.lndays_show ;

INTO CURSOR CUR_TEMP &&

ENDIF

SELECT CUR_TEMP

IF RECCOUNT()>0

CURSORTOXML("CUR_TEMP","lcXML",1,1,0,"1")

Page 19: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

ENDIF

ENDIF

CLOSE TABLES ALL

RETURN lcXML

*/--------------------------------------------------------------------------/*

*

* MS VFP version..: 9.0

* Program-ID......: sp_user_login_xml.PRG

* Purpose.........: Проверка пароля и имени пользователя

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 22/05/2005

* Last edited.....: 06/05/2005

*

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

PROCEDURE sp_user_login_xml

PARAMETERS m.User_nick, m.PASSWORD

SET DELETED ON

PRIVATE m.lcXML

m.lcXML=-1 && в случае неуспеха ответ в числовом виде

IF LEN(m.User_nick)>=3 AND LEN(m.PASSWORD)>3

SELECT User_ID, User_nick, admin, ISBLOCKED FROM USERS WHERE ;

UPPER(USERS.User_nick)==UPPER(m.User_nick) ;

AND UPPER(USERS.PASSWORD)==UPPER(m.PASSWORD) INTO CURSOR user_exists

IF RECCOUNT('USER_EXISTS')>0 AND EMPTY(user_exists.ISBLOCKED)

* у нас есть такой пользователь

CURSORTOXML('user_exists',"lcXML",1,1,0,"1")

ENDIF

ENDIF

IF USED('USER_EXISTS')

USE IN user_exists

ENDIF

IF USED('USERS')

USE IN USERS

ENDIF

RETURN m.lcXML

Page 20: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

*/--------------------------------------------------------------------------/*

*

* MS VFP version..: 9.0

* Program-ID......: sp_user_login_id.PRG

* Purpose.........: Проверка пароля и имени пользователя

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 22/05/2005

* Last edited.....: 06/05/2005

*

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

PROCEDURE sp_user_login_id

PARAMETERS m.User_nick, m.PASSWORD

SET DELETED ON

PRIVATE m.lnreturn_parameter

m.lnreturn_parameter=-1 && в случае неуспеха ответ в числовом виде

IF LEN(m.User_nick)>=3 AND LEN(m.PASSWORD)>3

SELECT User_ID, User_nick, admin, ISBLOCKED FROM USERS WHERE ;

UPPER(USERS.User_nick)==UPPER(m.User_nick) ;

AND UPPER(USERS.PASSWORD)==UPPER(m.PASSWORD) INTO CURSOR user_exists

IF RECCOUNT('USER_EXISTS')>0 AND EMPTY(user_exists.ISBLOCKED)

* у нас есть такой пользователь

m.lnreturn_parameter=user_exists.User_ID

ENDIF

ENDIF

IF USED('USER_EXISTS')

USE IN user_exists

ENDIF

IF USED('USERS')

USE IN USERS

ENDIF

RETURN m.lnreturn_parameter

*/--------------------------------------------------------------------------/*

*

Page 21: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

* MS VFP version..: 9.0

* Program-ID......: sp_users_read_xml.PRG

* Purpose.........: Чтение списка пользователей с сервера

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 31/05/2005

* Last edited.....: 31/05/2005

*

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

PROCEDURE sp_users_read_xml

PARAMETERS m.lcUser_nick, m.lcpassword

SET DELETED ON

PRIVATE m.lnuser_id, lcXML

STORE 0 TO m.lnuser_id

m.lnuser_id=sp_user_login_id(m.lcUser_nick, m.lcpassword)

lcXML=-1 && в случае неуспеха ответ в числовом виде

IF m.lnuser_id>0

SELECT User_ID, User_nick FROM USERS ;

INTO CURSOR CUR_TEMP

IF RECCOUNT('CUR_TEMP')>0

CURSORTOXML("CUR_TEMP","lcXML",1,1,0,"1")

ENDIF

ENDIF

CLOSE TABLES ALL

RETURN lcXML

*/--------------------------------------------------------------------------/*

*

* MS VFP version..: 9.0

* Program-ID......: sp_new_message_add.PRG

* Purpose.........: Добавление нового сообщения в таблицы Mes_Header, Mes_body

* а так-же обновляем информацию у клиента

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 30/05/2005

* Last edited.....: 04/06/2005

Page 22: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

*

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

PROCEDURE sp_new_message_add

PARAMETERS m.User_nick, m.PASSWORD , m.lnUser_to, m.lcTITLE, m.lcMes_Body

SET DELETED ON

SET MULTILOCKS ON

PRIVATE m.lnreturn_parameter, m.lnuser_id, m.lnmes_id

m.lnreturn_parameter=-1

m.lnuser_id=sp_user_login_id(m.User_nick, m.PASSWORD)

IF m.lnuser_id>0

BEGIN TRANSACTION

TRY

INSERT INTO Mes_Header (User_from , User_to, WASUPDATED, TITLE, published) ;

VALUES ;

(m.lnuser_id,m.lnUser_to,DATETIME(),ALLTRIM(m.lcTITLE), DATETIME())

m.lnmes_id=GETAUTOINCVALUE(0)

INSERT INTO Mes_body (Mes_ID,User_from,MESSAGE,published ) ;

VALUES ;

(m.lnmes_id,m.lnuser_id, m.lcMes_Body, DATETIME())

UPDATE USERS SET lastvisit = DATETIME() WHERE User_ID=m.lnuser_id

END TRANSACTION

m.lnreturn_parameter=1

CATCH TO oException

ROLLBACK

FINALLY

ENDTRY

ENDIF

CLOSE TABLES ALL

RETURN m.lnreturn_parameter

*/--------------------------------------------------------------------------/*

*

* MS VFP version..: 9.0

* Program-ID......: sp_thread_read.PRG

* Purpose.........: Чтение всего потока одного сообщения с сервера

Page 23: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 04/06/2005

* Last edited.....: 06/06/2005

*

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

PROCEDURE sp_thread_read

PARAMETERS m.lcUser_nick, m.lcpassword, m.lnmes_id

SET DELETED ON

PRIVATE m.lnuser_id, m.lnadmin, lcXML

STORE 0 TO m.lnadmin, m.lnuser_id

m.lnuser_id=sp_user_login_id(m.lcUser_nick, m.lcpassword)

lcXML=-1 && в случае неуспеха ответ в числовом виде

IF m.lnuser_id>0

SELECT Mes_body.*,User_nick, city FROM Mes_body ;

LEFT OUTER JOIN USERS ON Mes_body.User_from=USERS.User_ID ;

WHERE Mes_ID=m.lnmes_id ;

INTO CURSOR CUR_TEMP &&

SELECT CUR_TEMP

IF RECCOUNT()>0

CURSORTOXML("CUR_TEMP","lcXML",1,1,0,"1")

ENDIF

ENDIF

CLOSE TABLES ALL

RETURN lcXML

*/--------------------------------------------------------------------------/*

*

* MS VFP version..: 9.0

* Program-ID......: sp_existed_message_add.PRG

* Purpose.........: Добавление нового сообщения в таблицу Mes_body

* а так-же обновляем информацию у клиента

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 05/05/2005

* Last edited.....: 06/06/2005

*

Page 24: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

PROCEDURE sp_existed_message_add

PARAMETERS m.User_nick, m.PASSWORD , m.lcMes_Body, m.lnmes_id

SET DELETED ON

SET MULTILOCKS ON

PRIVATE m.lnreturn_parameter, m.lnuser_id

m.lnreturn_parameter=-1

m.lnuser_id=sp_user_login_id(m.User_nick, m.PASSWORD)

IF m.lnuser_id>0

BEGIN TRANSACTION

TRY

INSERT INTO Mes_body (Mes_ID,User_from,MESSAGE,published ) ;

VALUES ;

(m.lnmes_id,m.lnuser_id, m.lcMes_Body, DATETIME())

UPDATE USERS SET lastvisit = DATETIME() WHERE User_ID=m.lnuser_id

END TRANSACTION

m.lnreturn_parameter=1

CATCH TO oException

ROLLBACK

FINALLY

ENDTRY

ENDIF

CLOSE TABLES ALL

RETURN m.lnreturn_parameter

*/--------------------------------------------------------------------------/*

*

* MS VFP version..: 9.0

* Program-ID......: sp_message_delete.PRG

* Purpose.........: Удаление всего потока сообщения с сервера

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 05/06/2005

* Last edited.....: 05/06/2005

*

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

Page 25: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

PROCEDURE sp_message_delete

PARAMETERS m.lcUser_nick, m.lcpassword, m.lnmes_id

SET DELETED ON

SET MULTILOCKS ON

PRIVATE m.lnuser_id, m.lnadmin, lcXML

STORE 0 TO m.lnadmin, m.lnuser_id

m.lnuser_id=sp_user_login_id(m.lcUser_nick, m.lcpassword)

m.lnadmin=sp_chk_admin(m.lnuser_id)

m.lnreturn_parameter=-1 && в случае неуспеха ответ в числовом виде

IF m.lnuser_id>0 AND m.lnadmin>0

BEGIN TRANSACTION

TRY

DELETE FROM Mes_Header WHERE Mes_ID=m.lnmes_id

DELETE FROM Mes_body WHERE Mes_ID=m.lnmes_id

UPDATE USERS SET lastvisit = DATETIME() WHERE User_ID=m.lnuser_id

END TRANSACTION

m.lnreturn_parameter=1

CATCH TO oException

ROLLBACK

FINALLY

ENDTRY

ENDIF

CLOSE TABLES ALL

RETURN m.lnreturn_parameter

*/--------------------------------------------------------------------------/*

*

* MS VFP version..: 9.0

* Program-ID......: sp_answer_delete.PRG

* Purpose.........: Удаление одного ответа из сообщения с сервера

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 05/06/2005

* Last edited.....: 05/06/2005

*

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

PROCEDURE sp_answer_delete

Page 26: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

PARAMETERS m.lcUser_nick, m.lcpassword, m.lnReply_id, m.lnmes_id

SET DELETED ON

SET MULTILOCKS ON

PRIVATE m.lnuser_id, m.lnadmin, lcXML

STORE 0 TO m.lnadmin, m.lnuser_id

m.lnuser_id=sp_user_login_id(m.lcUser_nick, m.lcpassword)

m.lnadmin=sp_chk_admin(m.lnuser_id)

m.lnreturn_parameter=-1 && в случае неуспеха ответ в числовом виде

IF m.lnuser_id>0 AND m.lnadmin>0

BEGIN TRANSACTION

TRY

DELETE FROM Mes_body WHERE Reply_ID=m.lnReply_id

* теперь смотрим - остались ли еще сообщения и если нет - то удаляем

* и заголовок сообщения

SELECT COUNT(Mes_ID) AS RECORDS ;

FROM Mes_body ;

WHERE Mes_ID=m.lnmes_id ;

INTO CURSOR CUR_TEMP

SELECT CUR_TEMP

IF CUR_TEMP.RECORDS=0

DELETE FROM Mes_Header WHERE Mes_ID=m.lnmes_id

ENDIF

UPDATE USERS SET lastvisit = DATETIME() WHERE User_ID=m.lnuser_id

END TRANSACTION

m.lnreturn_parameter=1

CATCH TO oException

ROLLBACK

FINALLY

ENDTRY

ENDIF

CLOSE TABLES ALL

RETURN m.lnreturn_parameter

*/--------------------------------------------------------------------------/*

*

* MS VFP version..: 9.0

* Program-ID......: sp_users_profile_read_xml.PRG

* Purpose.........: Чтение профиля пользователя с сервера

Page 27: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 06/06/2005

* Last edited.....: 06/06/2005

*

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

PROCEDURE sp_users_profile_read_xml

PARAMETERS m.lcUser_nick, m.lcpassword, m.lnUserProfile_ID

SET DELETED ON

PRIVATE m.lnuser_id, lcXML, m.lnadmin

STORE 0 TO m.lnuser_id

m.lnuser_id=sp_user_login_id(m.lcUser_nick, m.lcpassword)

m.lnadmin=sp_chk_admin(m.lnuser_id)

lcXML=-1 && в случае неуспеха ответ в числовом виде

IF m.lnuser_id>0 AND m.lnadmin>0

SELECT * FROM USERS ;

INTO CURSOR CUR_TEMP WHERE User_ID=m.lnUserProfile_ID READWRITE NOFILTER

IF RECCOUNT('CUR_TEMP')=0

SELECT CUR_TEMP

APPEND BLANK

ENDIF

CURSORTOXML("CUR_TEMP","lcXML",1,1,0,"1")

ENDIF

CLOSE TABLES ALL

RETURN lcXML

*/--------------------------------------------------------------------------/*

*

* MS VFP version..: 9.0

* Program-ID......: sp_users_add_edit.PRG

* Purpose.........: Добавление/изменение профиля клиента

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 06/06/2005

* Last edited.....: 06/06/2005

*

* (С) www.sergey.co.uk 2005

Page 28: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

*/--------------------------------------------------------------------------/*

PROCEDURE sp_users_add_edit

PARAMETERS m.lcUser_nick, m.lcpassword, m.lnUserProfile_ID, m.lcXML_Cursor

SET DELETED ON

SET MULTILOCKS ON

PRIVATE m.lnuser_id, m.lnadmin, lcXML

STORE 0 TO m.lnadmin, m.lnuser_id

m.lnuser_id=sp_user_login_id(m.lcUser_nick, m.lcpassword)

m.lnadmin=sp_chk_admin(m.lnuser_id)

m.lnreturn_parameter=-1 && в случае неуспеха ответ в числовом виде

IF m.lnuser_id>0 AND m.lnadmin>0 AND !EMPTY(m.lcXML_Cursor)

XMLTOCURSOR(m.lcXML_Cursor,'TMCURSOR',4)

SELECT TMCURSOR

IF RECCOUNT()>0 && у нас есть работа

IF m.lnUserProfile_ID>0 && обновление существующих данных

BEGIN TRANSACTION

TRY

* это конечно узкое место, но нам хотелось все сделать с помощью CRUD команд

UPDATE USERS SET User_nick=TMCURSOR.User_nick, PASSWORD = TMCURSOR.PASSWORD,;

email=TMCURSOR.email, city=TMCURSOR.city,admin = TMCURSOR.admin, ;

ISBLOCKED=TMCURSOR.ISBLOCKED ;

WHERE User_ID=m.lnUserProfile_ID

END TRANSACTION

m.lnreturn_parameter=1

CATCH TO oException

ROLLBACK

FINALLY

ENDTRY

ELSE && добавление нового клиента

BEGIN TRANSACTION

TRY

INSERT INTO USERS ;

(User_nick, PASSWORD , email, city, ;

admin , register, lastvisit, ISBLOCKED ) ;

VALUES ;

(TMCURSOR.User_nick,TMCURSOR.PASSWORD,TMCURSOR.email,TMCURSOR.city,;

TMCURSOR.admin, DATETIME(), DATETIME(),TMCURSOR.ISBLOCKED)

END TRANSACTION

Page 29: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

m.lnreturn_parameter=1

CATCH TO oException

ROLLBACK

FINALLY

ENDTRY

ENDIF

ELSE && нечего делать

ENDIF

ENDIF

CLOSE TABLES ALL

RETURN m.lnreturn_parameter

Stored Procedures DBWS.DBC

Теперь, собственно, сам текст этой небольшой процедуры, которая создает эти ХП:

*/-----------------------------------------------------------------------/*

*

* MS VFP version..: 9.0

* Program-ID......: Create_SP.PRG

* Purpose.........: Создание Хранимых Процедур для базы данных DBWS.DBC

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 22/05/2005

* Last edited.....: 05/06/2005

*

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

PUBLIC m.pcpath

m.pcpath='C:\WS_MESSAGE\SERVER\'

OPEN DATABASE (m.pcpath+'DBWS.DBC')

APPEND PROCEDURES FROM (m.pcpath+'SP_PROCEDURES.TXT') as 1251 OVERWRITE

CLOSE DATABASES

Create_SP.PRG Кстати, в проекте, который Вы можете скачать ЗДЕСЬ (файл ws_mes_serv.zip 34 Kb) , так и сделано.Второй путь - открыть базу данных, написать команду MODIFY PROCEDURE и в открывшееся окно скопировать текст всех хранимых процедур.

Page 30: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

При отладке ХП могут иногда возникнуть проблемы - не отображаются внесенные Вами изменения. Для этого Вам надо открыть базу данных в режиме EXCLUSIVE и выполнить команду PACK DATABASE.Теперь солидная "ложка дегтя" к нашей "бочке меда". Дело в том, что ряд разработчиков используют базы данных FoxPro и для других приложений, например, в ASP.NET. Работа с базами данных осуществляется с помощью Visual FoxPro OLE DB Provider, который, к сожалению, пока все еще не поддерживает структуру TRY..CATCH..ENDTRY. В этом случае нам придется обойтись старыми приемами, основанными на буферизации таблиц и вложенных транзакциях. Для простоты повествования приведем текст примера только для одной хранимой процедуры sp_message_delete(): 

*/--------------------------------------------------------------------------/*

*

* MS VFP version..: 9.0

* Program-ID......: sp_message_delete.PRG

* Purpose.........: Удаление всего потока сообщения с сервера

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 05/06/2005

* Last edited.....: 05/06/2005

*

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

PROCEDURE sp_message_delete

PARAMETERS m.lcUser_nick, m.lcpassword, m.lnmes_id

SET DELETED ON

SET MULTILOCKS ON

PRIVATE m.lnuser_id, m.lnadmin, lcXML

STORE 0 TO m.lnadmin, m.lnuser_id

m.lnuser_id=sp_user_login_id(m.lcUser_nick, m.lcpassword)

m.lnadmin=sp_chk_admin(m.lnuser_id)

m.lnreturn_parameter=-1 && в случае неуспеха ответ в числовом виде

CLOSE TABLES ALL

SELECT 0

USE MES_HEADER SHARED

=CURSORSETPROP("Buffering" ,5,'MES_HEADER' )

SELECT 0

USE MES_BODY SHARED

Page 31: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

=CURSORSETPROP("Buffering" ,5,'MES_BODY' )

SELECT 0

USE USERS ALIAS USERS SHARED

=CURSORSETPROP("Buffering" ,5,'USERS' )

SELECT 0

IF m.lnuser_id>0 AND m.lnadmin>0

LOCAL llRollBack

llRollBack=.F.

BEGIN TRANSACTION

DELETE FROM MES_HEADER WHERE Mes_ID=m.lnmes_id

DELETE FROM MES_BODY WHERE Mes_ID=m.lnmes_id

UPDATE USERS SET lastvisit = DATETIME() WHERE User_ID=m.lnuser_id

IF !TABLEUPDATE(2,.T.,'MES_HEADER')

llRollBack=.T.

ELSE

IF !TABLEUPDATE(2,.T.,'MES_BODY')

llRollBack=.T.

ELSE

IF !TABLEUPDATE(2,.T.,'USERS')

llRollBack=.T.

ENDIF

ENDIF

ENDIF

IF llRollBack

ROLLBACK

ELSE

END TRANSACTION

m.lnreturn_parameter=1

ENDIF

ENDIF

CLOSE TABLES ALL

RETURN m.lnreturn_parameter

Вариант ХП sp_message_delete() для Visual FoxPro OLE DB

Page 32: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

Provider Код как обычно прозрачен, так что думаю, что можно опустить объяснения. В скачиваемом файле (ws_mes_serv.zip 34 Kb)  процедура для создания Хранимых Процедур носит название CREATE_SP_OLEDB.PRG, а их тексты находятся в файле SP_PROCEDURES_OLEDB.TXT. Для примера с Web Service на основе FoxPro не имеет значения какие хранимые процедуры использовать, но Вам, как программисту FoxPro, должна быть понятна эта разница и ограничения, накладываемые Visual FoxPro OLE DB Provider.

Page 33: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

Статья: Web Services и MS Visual FoxPro Часть 3В этой статье :

Подробное создание прототипа WebService. Возможные проблемы.

Подробное создание прототипа Web Service.Создадим прототип Web Service. Этот WS будет иметь то же название, что и реальный, с одной лишь разницей - у него будет всего один метод (процедура), котрый будет возвращать 1. Здесь мы подробно опишем, как его создать, опубликовать и проверить его работу. Далее при создании WS для нашего реального проекта мы опустим все эти подробности. Мы надеемся, что такой подход упростит понимание рассматриваемой технологии. 1. Создадим директорий на Вашем компьютере C:\WS_MESSAGE\SERVER

2. Создадим в этом директории программу с именем ws_server.prg , поместив туда следующий код:

*/--------------------------------------------------------------------------/*** MS VFP version..: 9.0 (так как применим новые данные совместимые с SQL Server)* Program-ID......: WS_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

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

Page 34: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

ENDPROC

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

ENDDEFINE

3. Cоздадим новый проект с названием ws_server и добавим туда созданную ранее программу ws_server.prg. По умолчанию этот модуль примет статус MAIN (то есть главный), что нам и надо:

4. Построим проект как multi-threaded COM server (DLL):

Вот мы и получили DLL, готовую к построению Web Service. К сожалению, пока у нас нет возможности использовать для создания нашего класса визуальные средства, так что приходится все писать

Page 35: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

руками в коде. Замечу еще, что наш класс на базе session должен быть определен как OLEPUBLIC. Сразу проведем тестирование созданной DLL. Для этого в командном окне наберем следующий код (набирается одна строка, затем она выполняется, затем следующая и т.д.):o=CREATEOBJECT('WS_SERVER.WS_MES_SERVER')

? o.test

RELEASE oЕсли у Вас все правильно, то на экране получим результат работы программы 1.И, наконец, пришло время опубликовать (или преобразовать обычной DLL в WS) наш первый Web Service. Для этого:

1. Нажмем правую клавишу мышки в окне проекта на имени нашей программы:

2. Появится окно Wizard Selection, в котором следует выбрать Web Services Publisher:

Page 36: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

3. После этого может появиться предупреждающее сообщение с короткими инструкциями, что надо делать (просто ответьте OK). Следующим появится Web Services Publishing  диалог:

4. Выбираем Advanced Button (на предыдущем рисунке эта кнопка обведена красным). Появляется диалог для определения места, где будет находиться создаваемый Web Service:

5. Для первого раза выберем  место New, изменим File Output Path и New Virtual Directory Name, как на следующем рисунке (и заодно выберем пункт Set selected URL as default Web service location, чтобы при последующих публикациях Web Service съэкономить наше время). Для выполнения наших инструкций нажимаем кнопку Create:

Page 37: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

6. После непродолжительной работы компьютера появляется экран в котором мы еще раз все сможем поменять (выбираем ISAPI - вроде как такой способ "прослушки" работает быстрее, чем ASP):

7. В принципе, все у нас выбрано правильно. Рекомендую только заглянуть во вкладку Methods:

Page 38: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

8. Дело в том, что позже, при создании новых методов в программе, они не будут автоматически выбираться построителем. Сейчас у Вас выбран единственный метод test. В будущем Вам надо будет делать это самостоятельно через эту вкладку (здесь же можно будет отключать неиспользуемые методы). Нажимаем кнопку OK. Возвращаемся в начальное окно публикации WS. Теперь надо нажать кнопку Generate:

9. Если у Вас все прошло нормально, то получите примерно такое системное сообщение:

Page 39: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

Ну вот и все! Не смотря на обилие рисунков, система в общем-то простая и прямолинейная. Сделав один раз, Вы сможете это повторять уже много раз без подсказок.

Осталось проверить работу данного Web Service. Как и в примере с проверкой COM DLL , наберите следующие команды в командном окне VFP:

o=CREATEOBJECT("MSSoap.SoapClient30")o.MSSoapInit("http://sergey04/ws_server/ws_mes_server.WSDL")? o.testrelease o

Если Вы получили на экране снова нашу любимую цифру 1 - это значит, что первый созданный Вами Web Service (и опубликованный пока что в Intranet) работает. Вот так незаметно для постороннего глаза Вы и научились программировать в глобальном масштабе.

Думаю, что для этого раздела достаточно. Теперь попробуем описать что делать, если что-то не работает.

Возможные проблемы.Автор данной статьи имеет сравнительно небольшой опыт в решении проблем (всего 5 лет), так как технология довольно молодая и в общем-то неплохо спроектирована. Если сравнивать количество отказов с .NET framework, то в последней было гораздо больше проблем и беспричинного отказа, который решался только удалением данной надстройки путем подачи команды aspnet_regiis.exe -ua  , а затем полной регистрации aspnet_regiis.exe -i , благо что MS предусмотрел все заранее. С SOAP 3.0 данный фокус, увы, не проходит. Если что-то стало неправильно работать, то простой переустановкой данного пакета ничего не добьешся - надо чистить регистр (regedit команда в окне RUN). Трудное это дело и, думаю, что до него у Вас не дойдет.

В данном разделе рассмотрим мелкие проблемы, которые могут возникнуть при совместной работе SOAP и IIS. Картинки будут с IIS 5.1 (WIndows XP professional), но в IIS 5.0, который есть в Windows 2000, они

Page 40: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

аналогичны. К сожалению, ничего не могу сказать про IIS 6.0 (Windows 2003), так как автору не удалось заставить в нем работать пакет SOAP 3.0 (несмотря на личные заверения Rick Strahl и мою полемику с ним в форуме UT, что все должно работать).

Итак, откроем Internet Information Services (выбрав свойства виртуального директория, где находится наш Web Service). У меня примерно вот такая картинка:

Построитель должен создать Application для нашего приложения. Если этого не произошло, то это можно сделать "вручную" (вместо кнопки Remove будет кнопка Create). Для решения глобальной проблемы  с Web Service - остутствие вызова по умолчанию обработчиков файлов с расширением WSDL - откроем окно Configuration:

Page 41: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

Если указанной строки нет, то ее надо добавить:

Причем для Executable Microsoft рекомендует внести строку:  "c:\progra~1\common~1\mssoap\Binaries\SOAPIS30.dll"(Особенно это касается Windows 2000, который не понимает пробелов в именах файлов и пути в этом окне ввода). Вот собственно и все. Теперь должно работать.

Page 42: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

Статья: Web Services и MS Visual FoxPro Часть 4В этой статье :

Web Service для нашего большого примера. Публикация Web Service (некоторые   ключевые   моменты).

 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

Page 43: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

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

Page 44: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 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 файл, в котором можно спрятать довольно большую таблицу или много других параметров (тем самым обходя ограничения на количество переданных праметров). В практической жизни таблицы я вначале сохраняю в виде текстового

Page 45: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

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

Публикация Web Service (некоторые ключевые моменты).Мы очень надеемся,что Вы проделали предыдущий пример и научились публиковать простейший WS. Мы не изменили имя файла для нашего примера, так что основные моменты остаются прежними. Первое отличие появится при построении Multi-Thread COM server (dll) - компилятор выдаст ошибку, что не может найти некоторые файлы, например:

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

То есть мы, по существу, получили полный список ХП нашей базы данных. В принципе, как мне посказали на форуме - можно включить нашу базу данных в проект, где находится наш WS и сообщения об ошибках исчезнут. Я этого не делал, так что у Вас есть возможность поэкспериментировать.Теперь следующая проблема. Если после создания Web Service Вы попытаетесь запустить его, он будет блокирован IIS (Internet Information Service). Вы не сможете создать DLL (а если Вы обращались

Page 46: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

к Вашей базе данных, то она тоже остается открытой, и Вы не сможете отбразить внесенные изменения в ХП). Для решения данных проблем необходимо перезапустить Ваш IIS. Например, как показано на следующей картинке:

Далее жмём OK

Если Вы нетерпеливы, то можно нажать кнопку немедленной перезагрузки в следующем экране:

Page 47: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

Приведенные снимки экранов актуальны для IIS 5.1 и ОС Windows XP. Для других версий продуктов они могут отличаться в ту или иную сторону. И не забудьте, что если Вы в сети, то сразу после загрузки кто-то может снова затребовать Ваш ресурс, и Вам придется повторить операцию с начала или просто остановить IIS и сделать свое дело.Вернемся снова к нашему Web Service. Просто покажу финальный экран, где будут видны все методы создаваемого нами WS:

Как мы видим, методов три. Мы специально оставили уже известный Вам метод test. В будущем Вы сможете легко проверить, работает Ваш Web Service или нет. И где проблема - в самом WS или в правах доступа к таблицам базы данных.Вот вроде бы и все. Web Service работает, но если мы попытаемся работать с реальными данными, Вы увидите, что не сможете ничего записать в Вашу базу данных. Причина тут простая - по умолчанию у WS нет права писать на Вашем компьютере. Далее наши объяснения

Page 48: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

будут сильно отличаться от того, где находится Ваш компьютер, и какая на нем установалена операционная система. Начнем с Windows XP на отдельно стоящей (не включенной в домен) рабочей станции. Находим папку, где у Вас WS (В нашем случае C:\ws_message\server):

Нажимаем правую кнопку на папке server, из всплывающего меню выбираем Property. На этой закладке выбираем ярлык Sharing, на котором производим следующие установки (но для этого у Вас должны быть права администратора на этот компьютер):

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

Page 49: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

компьютера по имени IUSR_SERGEY04 (это операцинная система создает этого клиента по умолчанию, где IUSR_ у всех компьютров постоянно, а SERGEY04 - имя Вашей машины (у Вас оно должно быть другим)). Вы можете сменить пароль этого клиента или даже дать доступ глобальному интернет-клиенту в Вашем домене. Посмореть клиента по умолчанию для Вашего IIS можно, нажав правую клавишу мышки на  Вашем виртуальном директории и выбрав в свойствах - Directory Security:

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

Page 50: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

Статья: Web Services и MS Visual FoxPro Часть 5В этой статье :

"Толстый клиент" для работы с Web Service.

 "Толстый клиент" для работы с Web Service.

Вы скорее всего слышали что-то о "тонком" и "толстом клиенте". В первом приближении тонкий (thin) клиент - это программа, с которой Вы можете работать на "голой" машине, на которой установлена только ОС и Browser. Можно ли для нашего Web Service создать такое приложение? Конечно, да! И очень легко. Самый простой способ - написать его на Classic ASP или ASP.NET. Но в этой статье мы рассмотрим толстый (fat) клиент. Данный клиент имеет преимущество: на таком компьютере можно установить библиотеку для запуска приложения FoxPro или даже полностью FoxPro, если это машина разработчика.Итак, начнем. Файл проекта поместим в директорий C:\ws_message\client\ . Общая картина будет примерно такой:

В головном модуле задаем глобальные переменные, производим проверку на недопустимость многократного запуска нашего приложения. В общем, обычная несложная рутина:

*/-----------------------------------------------------------------------/*

Page 51: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

*

* MS VFP version..: 9.0

* Program-ID......: MAIN.PRG

* Purpose.........: Главная программа клинета системы обмена сообщений

* Project Manager.:

* Programmer......: Sergey Chavlytko

* Start...........: 29/05/2005

* Last edited.....: 07/06/2005

*

* (С) www.sergey.co.uk 2005

*/--------------------------------------------------------------------------/*

IF _VFP.STARTMODE=0

_SCREEN.VISIBLE= .T.

* при запуске из среды разработки данная клавиша сохранит много Вашего времени

* если понадобится прервать выполнение программы.

ON KEY LABEL F12 SET SYSMENU TO DEFAULT

ELSE

_SCREEN.VISIBLE= .F.

ENDIF

* очищаем на всякий случай окружение

RELEASE ALL EXTENDED

CLEAR ALL

* делаем стандартные установки

SET CONFIRM ON

SET DELETED ON

SET EXACT OFF

SET EXCLUSIVE OFF

SET MULTILOCKS ON

SET SAFETY OFF

SET TALK OFF

SET DATE BRITISH

SET HOURS TO 24

* запоминаем номер версии программы в глобальной переменной

PUBLIC m.gcproramversion

m.gcproramversion=''

AGETFILEVERSION(AVER,'mesclient.exe')

Page 52: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

IF TYPE('AVER')#'U'

m.gcproramversion=' (ver: ' +AVER(11)+')'

ENDIF

PUBLIC m.gltransact

m.gltransact=.f.

* проверяем наличие предыдущей копии программы в памяти

IF AppAlreadyRunning()

=MESSAGEBOX("Вы конечно извините, но запустить данную программу "+ ;

"можно только один раз...", 0 + 16 +0, ;

"Ошибка в течении старта программы")

QUIT

ENDIF

* создаем переменные путей для создания временных таблиц и курсоров

* в принципе сейчас они не нужны, но это хорошая привычка все указывать

* явно и мы будем ей следовать...

PUBLIC m.gctmp

m.gctmp=SYS(2023)+'\'

PUBLIC m.gccurdir

m.gccurdir=SYS(5)+SYS(2003)+'\'

* явно определяем установки среды, которые будут видны во всей программе

* обычно эту информацию следует записывать во внешний DBF файл конфигурации

* если Вы все повторяете за нами все, то скорее всего Вам не надо будет менять

* имя Web Service (localhost - это только для Вашей локальной машины)

* если Вы будете использовать WS в Intranet - то замените на имя Вашей машины

* (например SERGEY04)

* при использовании в Internet - на реальный адрес...

*

PUBLIC gcwebserv

gcwebserv='http://localhost/ws_server/ws_mes_server.wsdl'

* объявляем глобальные переменные, которые потом будем использовать в программе

* мы будем использовать этот вариант для простоты, хотя в последнее время реко-

* мендуют создавать глобальный объект приложение и менять его свойства...

PUBLIC m.gclog, m.gcpsw, m.gcadmin,m.gnuser_id

STORE SPACE(10) TO m.gclog, m.gcpsw

Page 53: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

m.gcadmin=0

m.gnuser_id=0

DO FORM frmmain

READ EVENTS

QUIT

* функция избежания повтороного запуска программы

FUNCTION AppAlreadyRunning

LOCAL hsem, lpszSemName

#DEFINE ERROR_ALREADY_EXISTS 183

DECLARE INTEGER GetLastError IN win32API

DECLARE INTEGER CreateSemaphore IN WIN32API ;

STRING @ lpSemaphoreAttributes, ;

LONG lInitialCount, ;

LONG lMaximumCount, ;

STRING @ lpName

lpszSemName = 'MESCLIENT'

hsem = CreateSemaphore(0,0,1,lpszSemName)

RETURN (hsem # 0 AND GetLastError() == ERROR_ALREADY_EXISTS)

*

* оформим прием данных в виде универсальной процедуры

* в зависимости от передаваемых параметров меняем выполняемые

* функции на удаленном сервере

*

* m.lckey_word - имя выполняемой функции

* m.lcparameter1,m.lcparameter2 - передаваемые параметры

* m.lcNewTableName - имя создаваемого курсора (если не пустое)

*

*

*

*

PROCEDURE message_read

LPARAMETERS m.lckey_word,m.lcNewTableName,m.lcparameter1,m.lcparameter2,m.lcparameter3,;

m.lcparameter4,m.lcparameter5,m.lcparameter6

m.lcreturn=.F.

LOCAL loProxy

TRY

Page 54: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

loProxy=CREATEOBJECT("MSSOAP.SOapClient30")

WAIT WINDOW 'I am trying to connect to web server...' NOWAIT

loProxy.MSSoapInit(gcWebServ)

loProxy.ConnectorProperty("Timeout") = 90 * 1000 && milliseconds

WAIT WINDOW 'Receiving data...' NOWAIT

lcXML=loProxy.message_read(m.lckey_word,m.gclog,m.gcpsw,m.lcparameter1,m.lcparameter2,;

m.lcparameter3,m.lcparameter4,m.lcparameter5,m.lcparameter6)

CATCH TO oErr

m.lcmess='('+ALLTRIM(STR(oErr.Errorno))+') '+TRIM(oErr.Details)

MESSAGEBOX(m.lcmess,0,'We cannot connect to your Web Server. Error: ',30000)

m.gcerror_form=SUBSTR(('Error during receiving: ('+ALLTRIM(STR(oErr.Errorno))+') '+;

TRIM(oErr.Details)),1,254)

EXIT

FINALLY

RELEASE loProxy

ENDTRY

WAIT WINDOW 'Operation has been completed...' TIMEOUT 0.1

*waIT WINDOW lcXML

*? lcXML

IF TYPE('lcXML')="C" AND LEN(lcXML)>30

XMLTOCURSOR(lcXML,m.lcNewTableName,4)

SELECT &lcNewTableName

IF RECCOUNT()>0

m.lcreturn=.T.

ELSE

m.lcreturn=.F.

ENDIF

ELSE

IF EMPTY(m.lcNewTableName) && for executive functions

IF (TYPE('lcXML')="N" AND lcXML=1) OR (TYPE('lcXML')="C" AND EVALUATE('VAL(lcXML)>=1'))

m.lcreturn=.T.

ELSE

m.lcreturn=.F.

ENDIF

ELSE

WAIT WINDOW 'We are very sorry, but we could not retrieve data from Web server ' TIMEOUT 5

ENDIF

ENDIF

Page 55: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

RETURN m.lcreturn

Немного заострим Ваше внимание на обработке ошибок в процедуре message_read. Она построена на простом анализе возвращаемого или нет параметра от удаленного Web Service. В принципе это все можно усложнить в Вашем реальном приложении, но мне для практических нужд такой нехитрой обработки вполне хватает.Далее разработаем основную форму frmmain.scx . Тут есть небольшая хитрость. Мы хотели, чтобы это приложение было как можно проще. Выбор пал на formset. У нас две формы: одна для регистрации клиентов, а вторая для непосредственно работы с данными. Если регистрация прошла неудачно, подается команда CLEAR EVENTS, и программа заканчивает свою работу.

На форме регистрации есть кнопка со странным названием "Д" - это кнопка для разработчика (Developer). Она съэкономит много Вашего времени - то есть при тестировании программы Вы автоматически будете проходить процесс регистрации в систему. Не забудьте только в методе формы INIT сделать ее видимой только для Вас:

* стандартный трюк, чтобы съэкономить время разработчика

IF _VFP.STARTMODE=0

THISFORM.cmdD.VISIBLE =.T.

ELSE

THISFORM.cmdD.VISIBLE =.F.

Page 56: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

ENDIF

Для того, чтобы наша форма была все время наверху и активна в метод формы ACTIVATE вносим код:

* помещаем наше окно в верхнем слое

DECLARE INTEGER SetForegroundWindow IN USER32 INTEGER

DECLARE INTEGER FindWindow IN USER32 STRING @ , STRING @

lnHWND=FindWindow(0, _Screen.Caption)

IF lnHWND>0

SetForegroundWindow(lnHWND)

ENDIF

Метод кнопки "Войти" наиболее сложен. Здесь уже идет вызов метода login нашего Web Service с передачей в качестве параметров имени пользователя и пароля. В результате получаем курсор ACCESS с некоторыми свойствами, которые мы используем в приложении. В реальной жизни это очень удобное место для передачи на клиент названия модулей внутри программы, к которым у клиента есть доступ или даже передача самих модулей; удачное место для проверки устарела ли программа клиента или нет и установки более свежей версии (опять же передача ее через Интернет). В общем, все ограничено только Вашей фантазией и деньгами клиента. В конце производим установки интерфейса в зависимости от прав клиента:

LOCAL loProxy

TRY

loProxy=CREATEOBJECT("MSSOAP.SOapClient30")

WAIT WINDOW 'Произвожу соединение с web server...' NOWAIT

loProxy.MSSoapInit(gcwebserv)

* устанавливаем время возможной задержки ответа от сервера

loProxy.ConnectorProperty("Timeout") = 90 * 1000 && milliseconds

WAIT WINDOW 'Идет прием данных...' NOWAIT

lcXML=loProxy.login(m.gclog,m.gcpsw)

CATCH TO oErr

m.lcmess='('+ALLTRIM(STR(oErr.ERRORNO))+') '+TRIM(oErr.DETAILS)

MESSAGEBOX(m.lcmess,0,'We cannot connect to your Web Server. Error: ',30000)

EXIT

FINALLY

RELEASE loProxy

ENDTRY

* теперь очень простая проверка на то, что вернулось на наш запрос

Page 57: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

IF TYPE('lcXML')="C".AND.LEN(lcXML)>25

WAIT WINDOW 'Получаем из XML файла курсор...' NOWAIT

XMLTOCURSOR(lcXML,"Access",0)

* в реальной жизни я пищу в этот курсор имена программных модулей,

* к которым имеет доступ данный клиент - ну а пока одна строка

SELECT ACCESS

m.gnuser_id=ACCESS.User_ID

m.gcadmin=ACCESS.Admin

ELSE

=MESSAGEBOX("Нам очень жаль, но Вы не смогли зайти в систему...", 0 + 16 +0,;

"Ошибка при подключению к удаленному серверу.", 10000)

CLEAR EVENTS

ENDIF

WAIT WINDOW 'Прием данных завершен...' TIMEOUT 0.1

* делаем некоторые контролы видимыми только для администратора

IF m.gcadmin=1

thisformset.frmMAIN.cmdDeleteMessage.Visible =.t.

thisformset.frMMAIN.cmdAddUserNew.Visible = .t.

thisformset.frMMAIN.cmdEditUser.Visible = .t.

ELSE

thisformset.frmMAIN.cmdDeleteMessage.Visible =.f.

thisformset.frMMAIN.cmdAddUserNew.Visible = .f.

thisformset.frMMAIN.cmdEditUser.Visible = .f.

ENDIF

thisformset.frmLOGIN.Visible =.f.

thisformset.frmMAIN.Visible =.t.

thisformset.frMMAIN.Caption=('Система обмена сообщениями ('+alltrim(m.gclog)+')')

thisform.Release

После успешной регистрации клиент попадает на основную форму работы с данными. Как обычно - данных нет. Они запрашиваются путем нажатия кнопки "Освежить данные":

THISFORM.timer1.RESET

IF !EMPTY(m.gclog) AND !EMPTY(m.gcpsw)

Page 58: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

IF USED('MESSAGES')

SELECT MESSAGES

m.lnMes_ID=MESSAGES.Mes_ID

SET FILTER TO

ELSE

m.lnMes_ID=0

ENDIF

IF message_read('READ_MESSAGES_START','MESSAGES',DATE(),THISFORM.spnDaysUpdate.VALUE)

THISFORM.grid1.RECORDSOURCE=''

THISFORM.grid1.RECORDSOURCE='MESSAGES'

THISFORM.grid1.INIT()

SELECT MESSAGES

IF !EMPTY(m.lnMes_ID)

LOCATE FOR m.lnMes_ID=MESSAGES.Mes_ID

ELSE

GOTO BOTTOM

ENDIF

thisformset.counter=thisformset.counter+1

THISFORM.lblmessage.CAPTION = 'Последнее обновление с сервера: '+;

TTOC(DATETIME())+' ('+ALLTRIM(STR(thisformset.counter))+')'

ELSE

THISFORM.grid1.RECORDSOURCE=''

ENDIF

ENDIF

THISFORM.grid1.REFRESH()

THISFORM.grid1.SETFOCUS()

THISFORM.timer1.RESET

Ничего сложного - некоторые нюансы только с установками Grid, так как мы после приема данных заново воссоздаем курсор MESSAGES. Основную работу мы возложили на метод INIT в нашем Grid (не забывая при этом каждый раз очищать DataSource в основной программе вызова):

*

Page 59: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

* пробуем построить красивый Grid

*

IF USED('MESSAGES') && на всякий случай проверим наличие открытого курсора

THIS.READONLY= .T.

THIS.DELETEMARK= .F.

THIS.SCROLLBARS= 2

THIS.GRIDLINES= 0

*!* THIS.FONTSIZE= 9

*!* THIS.ROWHEIGHT = 20

THIS.COLUMNCOUNT = 6

THIS.ALLOWCELLSELECTION = .F.

WITH THIS.column1

.ALIGNMENT=1

.WIDTH=60

.CONTROLSOURCE="MESSAGES.Mes_ID"

.header1.CAPTION='Сообщ. No'

.header1.ALIGNMENT=2

.READONLY=.T.

ENDWITH

WITH THIS.column2

.WIDTH=70

.ALIGNMENT=0

.CONTROLSOURCE='MESSAGES.User_nick'

.header1.CAPTION='Автор'

.header1.ALIGNMENT=2

.READONLY=.T.

ENDWITH

WITH THIS.column3

.WIDTH=100

.ALIGNMENT=0

.CONTROLSOURCE='MESSAGES.city'

.header1.CAPTION='Откуда'

.header1.ALIGNMENT=2

.READONLY=.T.

ENDWITH

Page 60: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

WITH THIS.column4

.ALIGNMENT=0

.WIDTH=100

.FONTSIZE=8

.CONTROLSOURCE="MESSAGES.published"

.header1.CAPTION='Опубликовано'

.header1.ALIGNMENT=2

ENDWITH

WITH THIS.column5

.ALIGNMENT=0

.WIDTH=100

.FONTSIZE=8

.CONTROLSOURCE="MESSAGES.WASUPDATED"

.header1.CAPTION='Изменено'

.header1.ALIGNMENT=2

ENDWITH

WITH THIS.column6

.ALIGNMENT=0

.WIDTH=380

.CONTROLSOURCE="MESSAGES.TITLE"

.header1.CAPTION='Тема'

.header1.ALIGNMENT=2

.READONLY=.T.

ENDWITH

* раскрасим немного строки

THISFORM.grid1.SETALL("DynamicBACKColor", ;

"IIF(MESSAGES.User_to=m.gnuser_id , RGB(185,255,185),"+;

"IIF(MESSAGES.User_from=m.gnuser_id,RGB(217,217,255),RGB(255,255,255)) )", "Column")

* поощрим желание некоторых клиентов прочитать сообщение по двойному нажатии

* левой клавиши мышки (а заодно и по правой клавише)

BINDEVENT(THIS,"Dblclick",THISFORMSET,"Read_Message",1)

BINDEVENT(THIS,"Rightclick",THISFORMSET,"Read_Message",1)

ENDIF

Все строим "вручную". Может быть это и не очень эффективный прием программирования, но зато наглядный. Очень полезна команда BINDEVENT, появившаяся в VFP 8.0 - она одной строкой позволяет

Page 61: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

делать "фантастические вещи". Единственное уточнение - метод "Read_Message" создаем в главной FormSet.

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

В общем-то стандартная форма ввода данных. Интерес для нас представляет метод Click() кнопки "Сохранить".

IF THISFORM.newmessage=.T.

IF EMPTY(THISFORM.txtUser_nick.VALUE)

MESSAGEBOX("Псевдоним(Login)","Пожалуйста, заполните следующее поле",64,3000)

THISFORM.txtUser_nick.SETFOCUS

RETURN

ENDIF

IF EMPTY(THISFORM.txtPassword.VALUE)

MESSAGEBOX("Пароль.",;

"Пожалуйста, заполните следующее поле",64,3000)

THISFORM.txtPassword.SETFOCUS

RETURN

Page 62: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

ENDIF

* для простоты дальнейшего развития системы просто передаем весь курсор

* данный пример показывает как передавать на сервер курсор FoxPro

* все как обычно - в виде символьной строки (XML)

IF USED('USERS_PROF')

SELECT USERS_PROF

CURSORTOXML("USERS_PROF","lcXML",1,1,0,"1")

ELSE

lcXML=""

ENDIF

IF message_read('ADD_NEW_USER','',(THISFORM.text2.VALUE),lcXML)

THISFORM.RELEASE

ELSE

* в случае неудачи - просто снова возвращаемся в экран ввода нового сообщения

=MESSAGEBOX("Нам очень жаль, но Вы не смогли опубликовать данные...", 0 + 16 +0,;

"Ошибка при подключению к удаленному серверу.", 10000)

ENDIF

ELSE

IF EMPTY(THISFORM.txtUser_nick.VALUE)

MESSAGEBOX("Псевдоним(Login)","Пожалуйста, заполните следующее поле",64,3000)

THISFORM.txtUser_nick.SETFOCUS

RETURN

ENDIF

IF EMPTY(THISFORM.txtPassword.VALUE)

MESSAGEBOX("Пароль.",;

"Пожалуйста, заполните следующее поле",64,3000)

THISFORM.txtPassword.SETFOCUS

RETURN

ENDIF

* для простоты дальнейшего развития системы просто передаем весь курсор

* данный пример показывает как передавать на сервер курсор FoxPro

* все как обычно - в виде символьной строки (XML)

IF USED('USERS_PROF')

SELECT USERS_PROF

Page 63: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

CURSORTOXML("USERS_PROF","lcXML",1,1,0,"1")

ELSE

lcXML=""

ENDIF

IF message_read('ADD_NEW_USER','',(THISFORM.text2.VALUE),lcXML)

THISFORM.RELEASE

ELSE

* в случае неудачи - просто снова возвращаемся в экран ввода нового сообщения

=MESSAGEBOX("Нам очень жаль, но Вы не смогли опубликовать данные...", 0 + 16 +0,;

"Ошибка при подключению к удаленному серверу.", 10000)

ENDIF

ENDIF

Часть проверок мы все-таки производим на стороне клиента, чтобы не загружать наш сервер лишней работой. В этом примере показано, как передать на сервер курсор. По умолчанию его размер не превышает 100 Kb. Для нас этого хватит, но на практике надо увеличить его размер. Делается это путем нехитрых манипуляций с реестром Windows:1. Запустим программу для редактирования реестра:

2. Найдем в реестре вхождение для ключа SOAPISAP:

Page 64: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

3. Отредактируем значение для ключа MaxPostSize (по умолчанию это значение около 102 Kb. Имейте ввиду, что это не размер передаваемого Вами файла, в котором будут присутствовать XML тэги, так что размер Вашего передаваемого файла будет много меньше этого значения).

Разумное значение для быстрого Интернета (512 Kb/s) считается в пределах 4-8 Mbytes...

Page 65: Статья: Web Services и MS Visual FoxPro Часть 1 · Web viewWeb Services и MS Visual FoxPro Часть 1 В этой статье : Для чего написана эта

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

Скачать исходные тексты для Клиента можно отсюда (файл ws_mes_client.zip 72 Kb) В архив включен даже откомпилированный файл приложения.