COM Server und WebServices in VFP und .NET

Werbung
Session D-WEB1
COM Server und WebServices
in VFP und .NET
Markus Winhard
Sie wollen eine Internetanwendung als Ergänzung einer bestehenden VFP-Windowsanwendung integrieren. Das
ist einer der wenigen Sektoren mit steigender Nachfrage. Um diese zu befriedigen können wir auf unser
bestehendes Wissen zurückgreifen, müssen aber auch neue Technologien mit einbinden.
Die von mir vorgestellten Lösungsvorschläge resultieren aus meiner eigenen Suche nach der passenden
Technologie und Entwicklungsumgebung. Sie haben sich bereits in der Praxis bewährt.
Zunächst war es mir wichtig, dass ich nicht das grundsätzliche Konzept meiner Anwendung ändern muss und
bewährte und lieb gewonnene Funktionalitäten erhalten bleiben. Des Weiteren musste gewährleistet sein, dass
mit den neuen „Hilfsmitteln“ meine Anwendung im Internet ähnlich performant und bedienerfreundlich ist wie in
meiner Desktopanwendung. Für den Anwender sollte sich in der Bedienung möglichst wenig verändern.
Dieser Vortrag liefert Ihnen das notwendige „Handwerkszeug“ um VFP und .Net gemeinsam zu verwenden. Was
Sie außerdem noch brauchen, um eine zeitgemäße Internetanwendung zu erstellen, lernen Sie in meinem zweiten
Vortrag Web-Frontends für VFP-Anwendungen.
Sowohl diese Vortragsunterlagen als auch die zugehörigen Begleitdateien werden bis zur Konferenz sicherlich
weiter
verbessert
werden.
Die
neueste
Version
können
Sie
hier
herunterladen:
http://www.bingo-ev.de/~mw368/devcon2006.html.
Wenn Sie die Beispiele auf Ihrem Rechner testen wollen, stellen Sie sicher, daß die in den Abschnitten
Deployment und Anlegen eines virtuellen Verzeichnisses dieses Dokuments genannten Voraussetzungen erfüllt
sind.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 1
COM Server und WebServices in VFP
Erstellen eines COM Servers in VFP
Da wir auf die mit VFP gelieferte Datenbank “Northwind” zugreifen wollen, erstellen wir ein neues Projekt mit
dem Namen “NorthwindData”. Sein Hauptprogramm ist ein PRG mit folgendem Aufbau:
*===========================================================
* Hauptprogramm des COM-Servers/WebService NorthwindData.
*===========================================================
DEFINE CLASS DataService AS Session OLEPUBLIC
ENDDEFINE
Der Name des PRGs ist beliebig.
Kompilieren Sie das Projekt zu einem “Multi-threaded COM server (dll)”.
Der neue COM Server wird automatisch unter Project > Project Info... > Servers eingetragen.
13. Visual FoxPro Entwicklerkonferenz 2006
2 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
Wie Sie an dem Listbox-Titel “Server classes” sehen, könnte eine COM DLL auch mehrere COM Server
enthalten.
Hinzufügen von Methoden zum COM Server
Damit unser neuer COM Server etwas nützt, braucht er Methoden.
DEFINE CLASS DataService AS Session OLEPUBLIC
#DEFINE ccNORTHWINDDATA "C:\Vfp9\Samples\Northwind\"
PROCEDURE GetTable( tcTable AS String ) AS String
LOCAL lcXML
OPEN DATABASE (ccNORTHWINDDATA + "Northwind.dbc") SHARED
USE (tcTable) SHARED
lcXML = This.TableToXML( ALIAS() )
CLOSE DATABASES ALL
RETURN lcXML
ENDPROC
PROTECTED PROCEDURE TableToXML
LPARAMETERS tcAlias
LOCAL lcXML
CURSORTOXML( tcAlias, "lcXML" )
RETURN lcXML
ENDPROC
ENDDEFINE
Methoden, die vom COM-Server veröffentlicht werden sollen, müssen in der “neueren” Schreibweise angelegt
werden. D.h., wir verwenden runde Klammern statt LPARAMETERS, der Datentyp jedes Parameters muß
angegeben werden und der Datentyp des Rückgabewerts muß angegeben werden.
Methoden, die nach außen nicht sichtbar sein sollen, versehen wir mit dem Schlüsselwort PROTECTED. Ich
habe mir angewöhnt, diese internen Methoden zur leichteren Unterscheidung in der “alten” Schreibweise
anzulegen. Tatsächlich ist es aber egal, ob Sie bei internen Methode, die “alte” oder die “neuere” Schreibweise
verwenden.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 3
Es ist, wie in VFP üblich, egal, ob Sie Ihre Methoden als PROCEDURE oder FUNCTION anlegen.
Testen des COM Servers
Zuerst sollten wir testen, ob unsere Klasse DataService in VFP funktioniert, ohne den Umweg über die COMSchnittstelle. Dazu fügen wir zu Beginn des Hauptprogramms folgenden Code ein:
* Test als VFP-Klasse.
LOCAL loDS
loDS = CREATEOBJECT( "DataService" )
ACTIVATE SCREEN
CLEAR
SET MEMOWIDTH TO 100
? loDS.GetTable( "Region" )
In Ihrem VFP-Hauptfenster sollte jetzt die Tabelle “Region” als XML angezeigt werden.
<?xml version = "1.0" encoding="Windows-1252" standalone="yes"?>
<VFPData>
<region>
<regionid>1</regionid>
<regiondescription>Eastern</regiondescription>
</region>
<region>
<regionid>2</regionid>
<regiondescription>Western</regiondescription>
</region>
<region>
<regionid>3</regionid>
<regiondescription>Northern</regiondescription>
</region>
<region>
<regionid>4</regionid>
<regiondescription>Southern</regiondescription>
</region>
</VFPData>
Damit die neuen Methoden auch in der COM Server DLL enthalten sind, müssen wir das Projekt erneut
kompilieren. Danach können wir den COM Server testen. Da zur Laufzeit nur der COM Server instantiiert, aber
nicht das Hauptprogramm ausgeführt wird, kann auch dieser Code problemlos zu Beginn des Hauptprogramms
unseres COM Servers eingefügt werden.
Nachdem der COM Server beim Kompilieren registriert wurde, kann Intellisense auf seine Methoden-Signaturen
zugreifen.
13. Visual FoxPro Entwicklerkonferenz 2006
4 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
Ein WebService für unseren COM Server
Ein VFP-WebService ist eigentlich nur eine Hülle um einen VFP-COM Server. Um unseren COM Server zu
einem WebService zu machen, lassen wir das COM Server Projekt geöffnet und rufen den Web Services Wizard
auf.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 5
Die Auswahl Automatically generate XML web service files during project build ist wichtig. Sie bewirkt, daß
dem Projekt ein Project Hook hinzugefügt wird, der vor dem Kompilieren dafür sorgt, daß der Webserver die
COM Server DLL freigibt. Ohne diesen Project Hook müßten Sie den Webservice jedesmal vor dem
Kompilieren manuell beenden oder VFP würde die Fehlermeldung anzeigen, daß die COM Server DLL nicht
überschrieben werden kann, solange sie ein anderer Prozess im Zugriff hat.
Vergewissern Sie sich unbedingt, daß alle öffentlichen COM Server Methoden, die Sie auch im WebService
veröffentlichen wollen, im Tabreiter “Methods” der [Advanced...] Dialogs ein Häkchen haben. Das ist eine
13. Visual FoxPro Entwicklerkonferenz 2006
6 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
beliebte Stolperfalle. Vor allem wenn man später einmal dem COM Server neue Methoden hinzufügt, muß man
den neuen Methoden in diesem Dialog ein Häkchen geben.
Nach einem Klick auf die Schaltfäche [Generate...] sollte folgende Meldung erscheinen:
Schließen Sie anschließend das COM Server Projekt und öffnen Sie es erneut, damit der Project Hook aktiv
werden kann.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 7
WebService in VFP testen
Auch diesen Testcode können wir wieder zu Beginn des Hauptprogramms unseres COM Server Projekts
einfügen. Durch Eingabe des Kürzels ws zeigt uns Intellisense einen Dialog, in dem wir den gewünschten
WebService auswählen können. Anschließend stehen die Methoden des WebService in Intellisense zur
Verfügung.
Ebenso die Methodensignaturen:
Reports
Der REPORT FORM Befehl wird in COM Server DLLs nicht unterstützt, er funktioniert nur in EXE COM
Servern. Das heißt, wir müssen alle Druckroutinen in einen separate COM Server EXE packen.
Wenn nun aus einer COM Server DLL (oder aus einem WebService) gedruckt werden soll, dann müssen wir in
einer Methode der COM Server DLL mit CREATEOBJECT() die COM Server EXE instantiieren und eine
Methode aufrufen, die das Drucken übernimmt.
VFP COM Server und WebServices
aus .Net-Anwendungen aufrufen
Grundsätzlich ist es egal, welche Art von .Net Anwendung wir dazu verwenden (ASP.Net-Anwendung, .NetWindowsanwendung, .Net-WebService, .Net-Konsolenanwendung), der .Net-Code ist immer derselbe. Da dieser
Vortrag die Grundlagen für meinen anderen Vortrag Web-Frontends für VFP-Anwendungen vermitteln soll,
verwende ich auch hier eine kleine ASP.Net-Anwendung.
ASP.Net Solution anlegen
Die Organisationseinheit für ein Programm in Visual Studio 2005 ist eine Solution. Eine Solution enthält
mindestens ein Projekt, kann aber auch mehrere Projekte enthalten.
13. Visual FoxPro Entwicklerkonferenz 2006
8 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 9
Wir erhalten eine neue Solution, die lediglich eine leere WebForm Default.aspx enthält. In der Solution wird
unterhalb der Default.aspx eine weitere Datei Default.apsx.cs angezeigt. Sie enthält den Quellcode der Webseite.
13. Visual FoxPro Entwicklerkonferenz 2006
10 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 11
VFP COM Server einbinden
Damit wir einen COM Server in einer .Net Solution aufrufen können, müssen wir die Solution zuerst mit dem
COM Server bekannt machen. Das ist notwendig, weil .Net COM Server nicht direkt aufruft, sondern um jeden
COM Server eine Hülle aus .Net Code baut. Rufen Sie dazu im Kontextmenü der Solution den Punkt Add
Reference auf.
13. Visual FoxPro Entwicklerkonferenz 2006
12 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
Im folgenden Dialog wechseln wir auf den Tabreiter COM und wählen die NorthwindData Type Library.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 13
Dabei erzeugt .Net die erwähnte Hülle um unseren COM Server als Interop.northwinddata.dll.
Beim Aufrufen der Methoden des COM Servers hilft uns Intellisense, wie wir es von VFP gewohnt sind.
13. Visual FoxPro Entwicklerkonferenz 2006
14 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 15
Mit dem folgenden Code holen wir den Inhalt der Tabelle Region der Northwind-Datenbank als XML und geben
das XML auf der Webseite aus.
protected void Page_Load(object sender, EventArgs e)
{
// COM Server instantiieren.
northwinddata.DataService loCOMServer =
new northwinddata.DataService();
// Methode aufrufen.
string lcXML = loCOMServer.GetTable("Region");
// XML auf der Webseite ausgeben.
Response.Write(lcXML);
Response.End();
}
Mit der Funktionstaste F5 starten wir die Webseite im Browser um das Ergebnis anzuzeigen. Beim ersten Aufruf
erscheint folgender Dialog, den wir mit [OK] bestätigen.
13. Visual FoxPro Entwicklerkonferenz 2006
16 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
Aufruf des Codes aus dem Click() eines Buttons
Da wir die WebForm Default.aspx im Laufe dieses Vortrags noch für weitere Beispiele verwenden werden,
verlagern wir den Code in einen Button.Dazu ziehen wir aus der Toolbox-Rubrik Standard einen Button auf die
WebForm. Die Caption das Buttons steht bei ASP.Net im Property Text. Wir setzen bei dem neuen Button den
Text COM Server aufrufen. Falls Sie das Name-Property suchen, das heißt in ASP.Net ID.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 17
Wenn Sie die Toolbox aus Platzgründen lieber nicht immer im Vordergrund haben wollen, dann aktivieren Sie
im Kontextmenü der Toolbox-Titelleiste den Modus Auto Hide.
Per Doppelklick auf den Button gelangen Sie wie in VFP in dern Code-Editor. Dabei wurde automatisch eine
Methode cmdCOMServer_Click() in der WebForm angelegt. Damit ASP.Net weiß, wann diese Methode
aufgerufen
werden
soll,
wurde
zusätzlich
dem
HTML
des
Buttons
das
Attribut
OnClick="cmdCOMServer_Click" hinzugefügt. Tatsächlich wird hier zum Zeitpunkt des Kompilierens
eine Art verstecktes BINDEVENTS() eingebaut, aber diese Details gehen über den Umfang dieses Vortrags
hinaus.
Nachdem wir den Code aus der Methode Page_Load() in die Methode cmdCOMServer_Click() verschoben
haben, sieht unsere WebForm-Klasse so aus:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void cmdCOMServer_Click(object sender, EventArgs e)
{
// COM Server instantiieren.
northwinddata.DataService loCOMServer =
new northwinddata.DataService();
// Methode aufrufen.
string lcXML = loCOMServer.GetTable("Region");
13. Visual FoxPro Entwicklerkonferenz 2006
18 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
// XML auf der Webseite ausgeben.
Response.Write(lcXML);
Response.End();
}
}
Variablen und Datentypen in .Net
Wenn Sie bisher noch nie Kontakt mit der Programmierung in einer .Net-Sprache hatten, dann werden Sie sich
sicherlich fragen, welche Bedeutung die einzelnen Teile der Zeile
northwinddata.DataService loCOMServer = new northwinddata.DataService();
haben. Zum leichteren Verständnis spalten wir diese Zeile in zwei Zeilen auf:
northwinddata.DataService loCOMServer;
loCOMServer = new northwinddata.DataService();
In VFP würde man das so schreiben:
LOCAL loCOMServer AS northwinddata.DataService
loCOMServer = NEWOBJECT("northwinddata.DataService")
Allerdings geht .Net noch einen Schritt weiter als VFP. Man muß in :Net keinen COM Server bauen um einer
Variable diese Klasse als Datentyp zuzuweisen. Das klappt auch mit jeder Klasse aus der aktuellen Solution und
mit allen Klassen des .Net Frameworks. Im Gegensatz zu VFP ist die Angabe des Datentyps aber nicht nur für
Intellisense wichtig, sondern auch für den Kompiler. Ein .Net Kompiler versucht viele Fehler im Quellcode
bereits beim Kompilieren zu erkennen, die VFP erst zur Laufzeit bemerkt. So kann der Kompiler z.B. prüfen, ob
ein Property oder eine Methode wirklich Bestandteil der verwendeten Klasse ist. Damit das funktioniert, muß der
Kompiler aber wissen, daß wir in der Variable loCOMServer eine Instanz der Klasse
northwinddata.DataService speichern wollen. Und das wiederum ist der Grund dafür, daß wir
northwinddata.DataService als Datentyp der Variable loCOMServer angeben müssen.
Und weil in.Net alles ein Objekt ist, ist dieses Konzept universell anwendbar. D.h., selbst so einfache Datentypen
wie String oder Integer sind eigentlich Instanzen der Klasse string bzw. int. und damit gelten dieselben
Regeln.
VFP WebService einbinden
Ziehen Sie einen zweiten Button aus der Toolbox auf die WebForm und setzen Sie sein Property
Text=”WebService aufrufen”.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 19
Damit wir einen WebService in einer .Net Solution aufrufen können, müssen wir wie beim COM Server die
Solution zuerst mit dem WebService bekannt machen. Auch hier baut .Net eine Hülle aus .Net Code um den
WebService. Rufen Sie dazu im Kontextmenü der Solution den Punkt Add Web Reference auf.
13. Visual FoxPro Entwicklerkonferenz 2006
20 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
Im folgenden Dialog rufen Sie die URL Ihres VFP-WebService auf und vergeben in der Textbox Web reference
name einen sinnvollen Namen für den WebService.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 21
Nach dem Hinzufügen des WebService zu unserer Solution können wir per Doppelklick die neue WebFormMethode cmdWebService_Click() erstellen und folgenden Code einfügen. Wie in VFP unterstützt uns auch
hierbei Intellisense.
protected void cmdWebService_Click(object sender, EventArgs e)
{
// WebService instantiieren.
NorthwindWebService.DataService loWS =
new NorthwindWebService.DataService();
// Methode aufrufen.
string lcXML = loWS.GetTable("Region");
// XML auf der Webseite ausgeben.
Response.Write(lcXML);
Response.End();
}
Sie werden beim ersten Aufruf des VFP WebService wahrscheinlich eine relativ lange Verzögerung bemerken.
Diese Verzögerung hat ihre Ursache darin, daß der WebServer unseren WebService aufgrund eines Timeouts
zwischenzeitlich entladen hat. Ab dem zweiten Aufruf werden Sie aber keinen Unterschied zum Aufruf eines
COM Servers mehr spüren. Um ganz sicherzugehen, werde wir das auch nachmessen. Aber dazu später mehr.
Da unser VFP WebService nur eine Hülle um unseren VFP COM Server ist, ist auch das auf der Webseite
angezeigte XML identisch.
13. Visual FoxPro Entwicklerkonferenz 2006
22 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
Das VFP Toolkit 2.0 für .Net 2.0
Bereits im Jahre 2002 haben sich ein paar findige VFP-Programmierer mit .Net beschäftigt. Um schneller
produktiv zu werden, wollten Sie die von VFP bekannten Funktionen auch in .Net verwenden. Also haben sie
eine Funktionssammlung geschrieben, die ca 200 der wichtigsten VFP-Funktionen in .Net nachbildet. Diese
Funktionssammlung liegt seitdem auf diversen Servern im Internet unverändert zum Download. Sie kann im
Prinzip unverändert in .Net 2.0 verwendet werden.
Allerdings bietet uns .Net 2.0 mit den „Partial Classes“ die Möglichkeit, Code aus mehreren Quellcode-Dateien
zu einer Klasse zusammenzufassen. Das hat in diesem Fall den Vorteil, daß man nicht mehr wissen muß, in
welcher der 10 Klassen eine VFP-Funktion zu finden ist. Es gibt nur noch eine einzige Klasse „VFP“, die alle
Funktionen enthält. Ich habe das VFP Toolkit für .Net entsprechend umgeschrieben, die Dokumentation angepaßt
und die Versionsnummer 2.0 vergeben. Sie finden das VFP Toolkit 2.0 für .Net 2.0 in den Begleitdateien dieses
Vortrags.
Hinzufügen von VFP-Funktionen zur Solution
Im Kontextmenü der Solution den Punkt „Add Reference...“ auswählen. Im Tabreiter „Browse“ die
VFPToolkitNET.dll aus den Begleitdateien dieses Vortrags auswählen.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 23
Damit die Methoden einer Klasse aus einer .Net-DLL im Quellcode einfach verwendet werden können müssen
wir in unseren Quellcode eine entsprechende „using“-Direktive zu Beginn der Quellcode-Datei (*.cs) aufnehmen.
Das entspricht in etwa einem SET CLASSLIB TO in VFP. Mehr dazu im nächsten Abschnitt.
Ein einfacher Performance-Test
Da wir uns nun jede Menge bekannte VFP-Funktionen in .Net zur Verfügung stehen, wollen wir das doch gleich
einmal ausprobieren. Lassen Sie uns die Zeit nehmen die es dauert, den COM Server bzw. den WebService zu
instantiieren und seine Methode GetType() aufzurufen.
Und weil wir schon dabei sind, rechnen wir auch die Zeit zum Freigeben der externen Resource “WebService”
dazu. Das Freigeben von externen Resourcen sollte laut .Net-Doktrin in einer Methode namens Dispose()
passieren. Für uns heißt das, daß wir als brave Programmierer bei jedem Objekt, das eine Methode Dispose() hat,
diese Methode aufrufen, sobald das Objekt nicht mehr benötigt wird.
So sieht unser neuer Quellcode aus:
// SET CLASSLIB TO...
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
// VFP-Funktionen einbinden.
using VFPToolkit;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
13. Visual FoxPro Entwicklerkonferenz 2006
24 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
}
protected void cmdCOMServer_Click(object sender, EventArgs e)
{
// Zeit nehmen.
double lnSeconds0 = Vfp.Seconds();
// COM Server instantiieren.
northwinddata.DataService loCOMServer =
new northwinddata.DataService();
// Methode aufrufen.
string lcXML = loCOMServer.GetTable("Region");
// Nochmal Zeit nehmen.
double lnSeconds1 = Vfp.Seconds();
// XML und Dauer auf der Webseite ausgeben.
Response.Write("<?Dauer = " + (lnSeconds1 - lnSeconds0) + " ?>");
Response.Write(lcXML);
Response.End();
}
protected void cmdWebService_Click(object sender, EventArgs e)
{
// Zeit nehmen.
double lnSeconds0 = Vfp.Seconds();
// WebService instantiieren.
NorthwindWebService.DataService loWS =
new NorthwindWebService.DataService();
// Methode aufrufen.
string lcXML = loWS.GetTable("Region");
// .Net auffordern, die vom WebService-Proxy
// belegten Resourcen freizugeben.
loWS.Dispose();
// Nochmal Zeit nehmen.
double lnSeconds1 = Vfp.Seconds();
// XML und Dauer auf der Webseite ausgeben.
Response.Write("<?Dauer = " + (lnSeconds1 - lnSeconds0) + " ?>");
Response.Write(lcXML);
Response.End();
}
}
Und hier kommt das Ergebnis.
Das Einfassen der Dauer mit “<?” und “?>” ist notwendig, da wir im Anschluß XML-Daten ausgeben. Ohne
diese Begrenzer würde der Internet Explorer das Ganze nicht mehr als gültiges XML akzeptieren und eine
Fehlermeldung anzeigen.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 25
Sowohl der COM Server als auch der WebService hatten Laufzeiten zwischen “nicht meßbar” und 0,3 Sekunden.
Wie Sie sehen ist es in unserer Testumgebung für die Performance unerheblich, ob wir unseren VFP-Code als
COM Server oder WebService aufrufen.
Nach Aussage anderer Programmierer, die bereits mehrere Projekte mit Net und COM Servern bzw.
WebServices durchgeführt haben, hat es sich in der Praxis durchgesetzt, auf Webseiten aus Gründen der
Sicherheit und der Skalierbarkeit bevorzugt WebServices zu verwenden. Im Windows-Desktop-Bereich fällt die
Entscheidung meist zugunsten der COM Server, da man nicht voraussetzen kann, daß immer ein lokaler
Webserver installiert ist.
Übergabe von komplexen Parametern
Um es gleich vorwegzunehmen: In einer Anwendung, die in mehr als einer Programmiersprache erstellt wird,
sollte man sich beim Austausch von Daten zwischen den beiden Sprachen am kleinsten gemeinsamen Nenner
orientieren. Alles andere führt nur zu erhöhtem Aufwand und damit zu erhöhten Kosten.
In einer idealen Welt
werden die Schnittstellen zwischen den beteiligten Sprachen bereits vor Beginn des eigentlichen Projekts
festgelegt. In der Regel wird man komplexe Daten als XML austauschen. Das XML-Format wurde extra für
diesen Zweck geschaffen und eignet sich in der Praxis tatsächlich hervorragend für diesen Einsatzzweck.
VFP und .Net können Daten im XML-Format sehr gut in das jeweils benötigte Format konvertieren. XML kann
problemlos nicht nur mit COM-Servern, sondern auch mit WebServices ausgetauscht werden. Binäre Formate
oder komplexe Objekte können meist nicht mit WebServices ausgetauscht werden.
13. Visual FoxPro Entwicklerkonferenz 2006
26 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
Wenn Sie meinen zweiten Vortrag Web-Frontends für VFP-Anwendungen ebenfalls besuchen, dann werden Sie
sehen, daß die Übergabe jeglicher Form von Daten per XML nicht nur leicht zu handhaben ist, sondern auch
noch performant ist.
Lassen Sie mich als Beispiel zwei Funktionen aus dem dotNetHelper.prg zeigen, das den Begleitdateien zu
diesem Vortrag beiliegt.
Die erste Funktion XMLFromCursors () wird gerne verwendet um alle Daten, die in einer .Net Windows Form
oder ASP.Net WebForm benötigt werden, in ein einziges XML zu verpacken.
*-------------------------------------------* Alle übergebenen Cursor in .Net DataSet
* kompatibles XML packen.
*-------------------------------------------FUNCTION XMLFromCursors
LPARAMETERS tcAliases
*-------------------------------------------* Setup.
*-------------------------------------------LOCAL i, lcXML, loXMLAdapter AS XMLAdapter, ;
lnSelect, lcAlias, lnRecno
lnSelect = SELECT(0)
*-------------------------------------------* XMLAdapter erstellen.
*-------------------------------------------loXMLAdapter = CREATEOBJECT( "XMLAdapter" )
loXMLAdapter.UTF8Encoded = .T.
&& Default in .Net.
*-------------------------------------------* Alle übergebenen Aliase in den XMLAdapter
* aufnehmen. Dabei sicherstellen, daß die
* Satzzeiger wiederhergestellt werden.
*-------------------------------------------FOR i = 1 TO GETWORDCOUNT( m.tcAliases, "," )
lcAlias = GETWORDNUM( m.tcAliases, i, "," )
SELECT (m.lcAlias)
lnRecno = RECNO()
m.loXMLAdapter.AddTableSchema( m.lcAlias )
SELECT (m.lcAlias)
LOCATE RECORD (m.lnRecno)
ENDFOR
*-------------------------------------------* XML ausgeben.
*-------------------------------------------m.loXMLAdapter.ToXML( "lcXML" )
*-------------------------------------------* Cleanup.
*-------------------------------------------loXMLAdapter = .NULL.
RELEASE loXMLAdapter
SELECT (m.lnSelect)
*
RETURN m.lcXML
ENDFUNC
Die zweite Funktion, ChangesFromDiffGram() verwendet man, um ein XML-DiffGram einzulesen. Ein XMLDiffGram enthält alle Änderungen, die die .Net-Anwendung an unseren Daten vorgenommen hat inklusive
Buffering (aktueller Wert / Wert vor der Änderung). Mit Hilfe der Klassen XMLAdapter und CursorAdapter
können diese Änderungen performant auf eine gepufferte Tabelle oder View übertragen werden.
ChangesFromDiffGram() ist so implementiert, daß es möglich ist, Update-Konflikte zu erkennen. Somit können
wir bei Bedarf darauf reagieren, wenn ein anderer User die Daten, die wir gerade speichern wollen,
zwischenzeitlich verändert hat.
Es ist zwar grundsätzlich möglich, Änderungen für mehrere Tabellen gleichzeitig zu übertragen. Zugunsten
besserer Lesbarkeit verzichtet der Code in ChangesFromDiffGram() aber auf diese Möglichkeit.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 27
*-------------------------------------------* Änderungen aus XML-DiffGram auf gepufferten
* Cursor übertragen. Das DiffGram muß ein
* Schema enthalten. Der Code geht davon aus,
* daß das DiffGram nur Schema und Änderungen
* für eine einzige Tabelle/View enthält.
*(..)Der Ersatz für die fehlerhafte
*(..)Funktion ApplyDiffGram().
*-------------------------------------------FUNCTION ChangesFromDiffGram
LPARAMETERS tcDiffGram, tcAlias, tcKeyFieldList, ;
tlForce, taErrorRecordNumbers
*-------------------------------------------* Setup.
*-------------------------------------------LOCAL lnSelect, lnRecno, loXMLAdapter AS XMLAdapter, ;
lcUpdatableFieldList, lcUpdateNameList, ;
loCursorAdapter AS CursorAdapter, i, lcFldState, ;
lcDiffGramAlias, lcField, llSuccess
lcDiffGramAlias = m.tcAlias + "_XML"
llSuccess = .F.
lnSelect = SELECT(0)
lnRecno = RECNO( m.tcAlias )
SELECT 0
*-------------------------------------------* DiffGram in temp. Cursor wandeln.
*-------------------------------------------loXMLAdapter = CREATEOBJECT( "XMLAdapter" )
WITH loXMLAdapter
.LoadXML( m.tcDiffGram )
.Tables[ 1 ].Alias = m.lcDiffGramAlias
.Tables[ 1 ].ChangesToCursor()
ENDWITH
*-------------------------------------------* Felder, die keine Änderung im Wert
* aufweisen, auf "nicht geändert" setzen.
*(..)Leider führt der XMLAdapter immer für
*(..)*alle* Felder einen REPLACE durch, statt
*(..)nur für die Felder, die im DiffGram
*(..)unterschiedliche Werte haben.
*-------------------------------------------SELECT (m.lcDiffGramAlias)
SCAN
lcFldState = GETFLDSTATE(-1)
*-------------------------------------------* Nur geänderte Sätze prüfen. Neu angelegte
* und gelöschte Sätze nicht prüfen.
*-------------------------------------------IF LEFT( m.lcFldState, 1 ) == "1"
&& Geänderter Satz.
FOR i = 1 TO LEN( m.lcFldState ) - 1
lcField = FIELD(i)
IF SUBSTR( m.lcFldState, i + 1, 1 ) == "2" ;
AND EVALUATE( m.lcField ) == OLDVAL( m.lcField )
SETFLDSTATE( i, 1 )
ENDIF
ENDFOR
ENDIF
ENDSCAN
*-------------------------------------------* CursorAdapter an den DiffGram-Cursor binden
* um die gänderten Felder des
* DiffGram-Cursors in die Basistabelle/-view
* zu übertragen. Das funktioniert wie eine
* View auf eine View.
*-------------------------------------------loCursorAdapter = CREATEOBJECT( "CursorAdapter" )
WITH loCursorAdapter
.BreakOnError = .T.
13. Visual FoxPro Entwicklerkonferenz 2006
28 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
.Alias = m.lcDiffGramAlias
.BufferModeOverride = 5
.DataSourceType = "NATIVE"
.WhereType = IIF( m.tlForce, 1, 3 )
.ConflictCheckType = IIF( m.tlForce, 2, 3 )
.Tables = m.tcAlias
.SelectCmd = "SELECT * FROM " + m.tcAlias
.KeyFieldList = m.tcKeyFieldList
*-------------------------------------------* Alle Felder des DiffGram-Cursors
* aktualisierbar machen, für die in der
* Basistabelle/-view ein gleichnamiges Feld
* existiert.
*-------------------------------------------lcUpdatableFieldList = ""
lcUpdateNameList = ""
AFIELDS( laFields, m.tcAlias )
tcAlias = LOWER( m.tcAlias )
FOR i = 1 TO AFIELDS( laFields_XML, m.lcDiffGramAlias )
*-------------------------------------------* Gibts das Feld auch in der
* Basistabelle/-view?
*-------------------------------------------IF ASCAN( laFields, laFields_XML[ i, 1 ], 1, -1, 1, 1+2 ) > 0
lcField = LOWER( laFields_XML[ i, 1 ] )
lcUpdatableFieldList = m.lcUpdatableFieldList +","+ ;
m.lcField
lcUpdateNameList = m.lcUpdateNameList +","+ ;
m.lcField +" "+ m.tcAlias +"."+ m.lcField
ENDIF
ENDFOR
.UpdatableFieldList = SUBSTR( m.lcUpdatableFieldList, 2 )
.UpdateNameList = SUBSTR( m.lcUpdateNameList, 2 )
*-------------------------------------------* DiffGram-Cursor an den CursorAdapter
* binden.
*-------------------------------------------.CursorAttach()
ENDWITH
*-------------------------------------------* Änderungen aus dem DiffGram-Cursor in die
* Basistabelle/-view übertragen.
*-------------------------------------------llSuccess = TABLEUPDATE( 2, m.tlForce, ;
m.lcDiffGramAlias, taErrorRecordNumbers )
*-------------------------------------------* Cleanup.
*(..)Der DiffGram-Cursor wird beim Freigeben
*(..)des CursorAdapters automatisch
*(..)geschlossen.
*-------------------------------------------loXMLAdapter = .NULL.
loCursorAdapter = .NULL.
RELEASE loXMLAdapter, loCursorAdapter
SELECT (m.tcAlias)
LOCATE RECORD (m.lnRecno)
SELECT (m.lnSelect)
*
RETURN m.llSuccess
ENDFUNC
Wenn die .Net-Abteilung schneller war,
dann kann es Ihnen passieren, daß Sie als VFP-Programmierer Schnittstellen bedienen müssen, wie man sie in
der .Net Welt gerne zwischen Servern und Clients verwendet. Dort werden Daten meist in Form von DataSets
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 29
verschickt. Ein DataSet ist am ehesten vergleichbar mit der VFP-Klasse Dataenvironment. D.h., ein DataSet
kann mehrere gepufferte Tabellen enthalten. Daneben kann es auch Relationen, Indizes und Filter enthalten.
Tatsächlich wandelt .Net ein DataSet bei bestimmten Transportmedien selbstständig ins XML-Format und wieder
zurück (das bekannteste Beispiel dafür sind SOAP-kompatible WebServices), aber davon merkt der .NetProgrammierer nichts.
Damit Sie als VFP-Programmierer auch nicht viel davon merken, habe ich die folgenden beiden Funktionen ins
dotNetHelper.prg aufgenommen.
*-------------------------------------------* dotNet DataSet in XML wandeln.
*(..)Bisher nur mit SOAP3-WebService
*(..)getestet.
*-------------------------------------------FUNCTION DataSetToXML
LPARAMETERS toDataSetDocument
*-------------------------------------------* Setup.
*-------------------------------------------LOCAL lcXML, loXMLAdapter AS XMLAdapter
*-------------------------------------------* DataSets als XML ausgeben.
*-------------------------------------------#IF .T.
*-------------------------------------------* Entweder so...
*-------------------------------------------lcXML = m.toDataSetDocument.item[0].parentNode.Xml
#ELSE
*-------------------------------------------* ...oder so.
*-------------------------------------------loXMLAdapter = CREATEOBJECT( "XMLAdapter" )
m.loXMLAdapter.Attach( m.toDataSetDocument )
m.loXMLAdapter.ToXML( "lcXML" )
#ENDIF
*-------------------------------------------* Cleanup.
*-------------------------------------------toDataSetDocument = .NULL.
loXMLAdapter = .NULL.
RELEASE toDataSetDocument, loXMLAdapter
*
RETURN m.lcXML
ENDFUNC
*-------------------------------------------* dotNet DataSet aus XML erzeugen.
*(..)Bisher nur mit SOAP3-WebService
*(..)getestet.
*-------------------------------------------FUNCTION XMLToDataSet
LPARAMETERS tcXML
*-------------------------------------------* Setup.
*-------------------------------------------LOCAL loDOM, loDataSetDocument
loDOM = CREATEOBJECT( "MSXML2.DomDocument" )
*-------------------------------------------* XML einlesen und als DataSet ausgeben.
*-------------------------------------------m.loDOM.LoadXML( m.tcXML )
loDataSetDocument = m.loDOM.DocumentElement.ChildNodes()
*-------------------------------------------* Cleanup.
*-------------------------------------------13. Visual FoxPro Entwicklerkonferenz 2006
30 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
loDOM = .NULL.
RELEASE loDOM
*
RETURN m.loDataSetDocument
ENDFUNC
Debuggen von VFP COM Servern
Zu diesem Thema gibt es zwei verschiedene Ansätze. Den ersten von Maurice de Beijer finden Sie unter
http://www.theproblemsolver.nl/aspdevelopmentanddebugging/index.htm. Er verwendet die Active Accessibility
API.
Der zweite Ansatz ist von Rick Strahl und eignet sich besonders zum Debuggen von VFP COM Servern, die
aus.Net aufgerufen werden. Hier wird es erklärt: http://west-wind.com/WebLog/posts/666.aspx.
Es ist gut zu wissen,. daß man die Möglichkeit hat, einen VFP COM Server zu debuggen, falls nötig. Allerdings
findet man nach meiner Erfahrung 99 Prozent der auftretenden Fehler wesentlich schneller, wenn man es so
macht, wie zu Anfang dieses Vortrags unter der Überschrift Testen des COM Servers erklärt. Da jeder VFP COM
Server im Inneren aus einer VFP-Klasse besteht, kann man diese Klasse auch direkt in der VFP
Entwicklungsumgebung (ohne den Umweg über COM) instantiieren und ihre Methoden aufrufen.
Protokollieren der Aufrufparameter
Wenn Sie einen Fehlerfall in einem COM Server erst nach der Auslieferung feststellen, dann ist es interessant,
die exakten Eingabeparameter zur Verfügung zu haben, die zum Fehler führten.
Diese Daten sind auch hilfreich, wenn Sie nach Änderungen an einer Methode Unit-Tests durchführen wollen. Da
Ihnen jede Menge Eingabeparameter und zugehörige Rückgabewerte zur Verfügung stehen, können Sie testen,
ob Ihre Methode sich nach außen noch genauso verhält wie vor der Änderung.
*===========================================================
* Protokollierung der eingehenden Anfragen und der
* ausgehenden Antworten eines COM Service oder WebServers.
*===========================================================
DEFINE CLASS Protokoll AS Session OLEPUBLIC
*-------------------------------------------* Name extra zuweisen, sonst bleibt er bei
* COM Servern leer.
*-------------------------------------------Name = "Protokoll"
PROTECTED cLogFile
cLogFile = ""
PROCEDURE GetData( tnID AS Integer ) AS String
LOCAL lcData
lcData = "Hallo Welt"
RETURN This.LogIt( lcData )
ENDPROC
PROCEDURE Init
*-------------------------------------------* Hier die Methode LogIt an alle öffentlichen
* Methoden des COM Servers binden.
*-------------------------------------------BINDEVENT( This, "GetData", This, "LogIt" )
*...
*-------------------------------------------* Pfad der Logdatei.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 31
*-------------------------------------------This.cLogFile = FORCEEXT( IIF( VERSION(2) == 2, ;
FULLPATH( ".\" ) + PROGRAM(), ;
_Vfp.ServerName ), ;
"log" )
ENDPROC
PROCEDURE LogIt
LPARAMETERS t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, ;
t11, t12, t13, t14, t15, t16, t17, t18, t19, t20
*-------------------------------------------* Setup.
*-------------------------------------------LOCAL lcCalledProgram, i, lcVar, laEvents[1], lcLogText
*-------------------------------------------* Name der Klasse und der aufgerufenen
* Methode.
*-------------------------------------------IF AEVENTS( laEvents, 0 ) == 0
lcCalledProgram = PROGRAM(PROGRAM(-1)-1)
lcCalledProgram = This.Name + "." + ;
SUBSTR( lcCalledProgram, AT( ".", lcCalledProgram ) + 1 )
ELSE
lcCalledProgram = This.Name + "." + ;
laEvents[ 2 ]
ENDIF
*-------------------------------------------* Uhrzeit.
*-------------------------------------------lcLogText = CHR(13) + ;
"*** " + STRTRAN(TTOC(DATETIME(),3),"T", " ") + " ***" + ;
CHR(13) + lcCalledProgram + CHR(13)
*-------------------------------------------* Alle Parameter, die der aufgerufenen
* Methode übergeben wurden, bzw. der Wert,
* der von ihr zurückgegeben wurde.
*-------------------------------------------FOR i = 1 TO PCOUNT()
lcLogText = lcLogText + ;
TRANSFORM(EVALUATE( "t" + LTRIM(STR( i )) )) + CHR(13)
ENDFOR
*-------------------------------------------* In Textdatei schreiben.
*-------------------------------------------STRTOFILE( lcLogText, This.cLogFile, .T. )
*-------------------------------------------* Rückgabewert zurückgeben.
*-------------------------------------------RETURN t1
ENDFUNC
ENDDEFINE
So sieht der Inhalt der Logdatei nach einem Aufruf der Methode GetData() aus.
*** 2006-11-10 03:32:10 ***
Protokoll.GETDATA
10
*** 2006-11-10 03:32:10 ***
Protokoll.GETDATA
Hallo Welt
13. Visual FoxPro Entwicklerkonferenz 2006
32 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
Deployment
Damit ein WebService auf einem Webserver installiert werden kann, müssen zuerst ein paar Vorausetzungen
erfüllt sein. Neben dem obligatorischen Webserver IIS muß installiert sein:

Die VFP Runtime. Das geht am leichtesten mit dem ProLib Runtime Installer (ftp://ftp.prolib.de/Public/VFP/
VFP9SP1RT.exe).

SOAP 3.0. Hier gibt es die am einfachsten zu installierende Variante direkt von Microsoft: soapsdk.exe
(http://www.microsoft.com/downloads/details.aspx?familyid=c943c0dd-ceec-4088-9753-86f052ec8450)

Ein IIS-Skript-Mapping, das die Dateiendung WSDL dem SOAP3-Listener zuordnet. Das ist ein Zweizeiler
in VFP:
loWSHelper = NEWOBJECT( "_WebServices", ;
IIF( VERSION(2)=0, "", HOME() + "FFC\" ) + "_WS3Utils.vcx" )
loWSHelper.CheckVDirMap( "IIS://localHost/w3svc/1/Root" )
Ob das Skript-Mapping bereits angelegt ist, können Sie auch hier nachsehen: Start > Einstellungen >
Systemsteuerung > Verwaltung > Internetdienste-Manager > Standardwebseite > Eigenschaften >
Basisverzeichnis > Konfiguration > Anwendungszuordnungen.
Achtung: Das manuelle Eintragen dieser Zuordnung ist leider so wie es hier dargestellt ist nicht möglich, da der
Standard-Installationspfad der SOAPIS30.dll ein Leerzeichen enthält. Faßt man den Installationspfad in
Anführungszeichen, dann läßt sich die Zuordnung zwar speichern, aber sie funktioniert nicht.
Wenn Sie die Zuordnung trotzdem einmal manuell vornehmen müssen, dann geben Sie den Pfad in MSDOS-8.3Schreibweise an. Die 8.3-Schreibweise einer Pfadangabe erhalten Sie am einfachsten, indem Sie eine MSDOSEingabeaufforderung öffnen, mit dem Befehl CD ins gewünschte Verzeichnis wechseln, und den Befehl
“command” eingeben.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 33
Installation des COM Servers
Da die Funktionalität von VFP WebServices in den zugehörigen COM Servern steckt, müssen wir die COM
Server DLL auf dem WebServer registrieren. Als Beispiel verwende ich einen fiktiven “HalloWelt”-WebService.
C:\Windows\System32\RegSvr32.exe HalloWelt.dll
Das Installationsverzeichnis kann ein beliebiges Verzeichnis auf dem Webserver sein.
Die von VFP beim Kompilieren ebenfalls generierten Dateien HalloWelt.TLB und HalloWelt.VBR müssen nach
meiner Erfahrung nicht auf den WebServer kopiert werden.
Installation der WSDL- und WSML-Dateien
Zu einem WebService gehören eine WSDL-Datei und zwei WSML-Dateien. Kopieren Sie alle drei Dateien in
ein Verzeichnis auf der Festplatte des Webservers, dem ein virtuelles Webverzeichnis zugeordnet ist.
Grundsätzlich kann dafür auch das Verzeichnis C:\InetPub\wwwRoot\ verwendet werden, viele Administratoren
sehen es aber nicht so gerne, wenn das Hauptverzeichnis ihres Webservers mit Dateien übersäht ist.
Im Fall unseres fiktiven“HalloWelt”-WebService lauten die Dateinamen

HalloWelt.WSDL

HalloWelt.WSML

HalloWeltClient.WSML
Nach dem Kopieren der drei genannten Dateien muß die WSDL-Datei noch an Ihre neue Heimat angepaßt
werden. Öffnen Sie dazu die Datei mit einem Text-Editor und suchen Sie am Ende der Datei den XML-Tag, der
mit <soap:address location beginnt. Passen Sie den Domain-Namen und das virtuelle Verzeichnis an den neuen
Installationsort an:
<soap:address location='http://www.meinedomain.de/HalloWelt.WSDL'/>
Ein erster Test in VFP
Nach erfolgreicher Installation kann unser fiktiver “HalloWelt”-WebService von einem anderen PC aus getestet
werden. Voraussetzung ist, daß auf diesem PC der SOAP Client 3.0 installiert ist.
LOCAL loWS
loWS = CREATEOBJECT( "MSSOAP.SoapClient30" )
loWS.MSSoapInit( "http://w2000/hallowelt.wsdl", ;
"hallowelt", "halloweltSoapPort" )
? loWS.HalloWelt()
13. Visual FoxPro Entwicklerkonferenz 2006
34 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
Anlegen eines virtuellen Verzeichnisses im IIS
Um die gezeigten Beispiele auf Ihrem PC auszuführen, erstellen Sie ein Verzeichnis devcon2006 auf Ihrer
Festplatte. Erstellen Sie ein Unterverzeichnis D-WEB1 und entpacken Sie die Beispieldateien
(D-WEB1_code.zip) in dieses Unterverzeichnis.
Legen Sie anschließend ein virtuelles Verzeichnis /devcon2006 in ihrem lokalen Internet Information Server an
und ordnen Sie diesem virtuellen Verzeichnis das soeben angelegte Verzeichnis devcon2006 auf Ihrer Festplatte
zu. Dazu öffnen Sie die Windows Management Konsole Internet-Informationsdienste. Sobald der IIS installiert
ist, finden Sie diese unter Start > Einstellungen > Systemsteuerung > Verwaltung > Internetdienste-Manager.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 35
13. Visual FoxPro Entwicklerkonferenz 2006
36 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 37
Der Vollständigkeit halber: Ein WebService in .Net
In Visual Studio 2005 legen Sie einen neuen WebService mit folgenden Schritten an: File > New Web Site >
ASP.NET Web Service. Visual Studio 2005 legt eine neue Webseite für Sie an und gibt den folgenden Code vor.
using
using
using
using
System;
System.Web;
System.Web.Services;
System.Web.Services.Protocols;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod]
public string HelloWorld() {
return "Hello World";
}
}
Starten Sie den WebService mit Taste F5.
13. Visual FoxPro Entwicklerkonferenz 2006
38 • D-WEB1
(Gruppe WEB)
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
Die URL, die wir zum Aufruf dieses WebService aus VFP benötigen, finden durch einen Klick auf den Link
Dienstbeschreibung.
Der Aufruf aus VFP sieht dann so aus.
LOCAL loService
loService = CREATEOBJECT( "MSSOAP.SoapClient30" )
m.loService.MSSoapInit( ;
"http://localhost:1055/WebService1/Service.asmx?WSDL", ;
"Service", "ServiceSoap" )
? m.loService.HelloWorld()
Famous last words
Dieses war der erste Streich… (so hieß es damals auch bei Wilhelm Busch) …und der zweite folgt sogleich. Nun
ja, nicht gleich, aber morgen in meinem zweiten Vortrag. Sie sind jetzt bereits in der Lage, eigene COM Server
und WebServices zu erstellen, zu debuggen und aus ASP.Net aufzurufen. Noch ein bischen Programmieren in
Visual Studio 2005 gelernt und schon kanns losgehen mit der Erweiterung Ihrer VFP-Anwendungen ins Web.
Aber halt! Ein paar wichtige Informationen brauchen sie noch. Besuchen Sie auch meinen zweiten Vortrag WebFrontends für VFP-Anwendungen und ich erzähle Ihnen den Rest. 
Bei Fragen zu diesem Skript oder den mitgelieferten Klassen erreichen Sie mich unter [email protected].
Ich stehe Ihnen auch gerne für Ihre Projekte zur Verfügung.
COM Server und WebServices in VFP und .NET
© 2006 Markus Winhard
(Gruppe WEB)
13. Visual FoxPro Entwicklerkonferenz 2006
D-WEB1 • 39
Herunterladen