Von APD über COM nach SOAP Teil 3

Nachdem in den letzten beiden Teilen die Grundlagen erläutert worden sind, werden wir heute einen kompletten SOAP-Webservice auf Basis eines Gupta-COM-Objekts erstellen.

Erstellen der COM-Funktion

Als Beispiel möchten wir Daten zu einem Ansprechpartner in einer SqlBase-Datenbank abspeichern.  Attribute des Ansprechpartners sollen Vorname, Nachname, Geburtstag und Glückszahl sein. Dazu erstellen wir im Gupta-COM-Objekt aus Teil 2 eine neue Funktion „ContactSave“:

Returns
 Boolean:
Parameters
 String: sFirstName
 String: sLastName
 Date/Time: dtBirthday
 Number: nLuckyNumber
  Use: VT_I4
 Receive String: rsErrorMsg

Local variables
 Number: nContactId
 Number: nFetch
 Sql Handle: hSql
 Boolean: bOk

Actions
 ! Ensures that ISLAND-Database is present and Contact-Table exists
 If ( TryConnectAndCheckDb( rsErrorMsg ) )
  If ( SqlConnect( hSql ) )
   ! get next id
   Call SqlPrepareAndExecute( hSql, 'SELECT MAX(ContactId) FROM GuptaComContact INTO :nContactId' )
   Call SqlFetchNext( hSql, nFetch )
   If ( NOT nContactId )
    Set nContactId = 0
   Set nContactId = nContactId + 1
   ! insert data
   Set bOk = SqlPrepareAndExecute( hSql, 'INSERT INTO GuptaComContact ( ContactId, FirstName, LastName, Birthday, LuckyNumber )
       VALUES ( :nContactId, :sFirstName, :sLastName, :dtBirthday, :nLuckyNumber)' ) 
   If ( bOk )
    Call SqlPrepareAndExecute( hSql, 'COMMIT' )
   Else
    Set rsErrorMsg = 'Sqlerror while inserting contact'
   ! disconnect everything - function call must be stateless!
   Call SqlDisconnect( hSql )
   Return bOk
  Else
   Return FALSE

Der vollständige Code ist kann hier heruntergeladen werden.

Erstellen des SOAP-Webservices

Hier das Kochrezept:

  • Starten von Visual WebDeveloper Express 2010
  • neue „Leere ASP.NET-Webanwendung mit Namen „GuptaSoap“ erstellen
  • im Projektmappenexplorer per rechter Maustaste / Hinzufügen / Neues Element dort den Webdienst auswählen, diesen GuptaSoap nennen

Sieht man sich die automatisch generierte Datei „GuptaSoap.asmx.cs“ an, ist bereits automatisch eine Webservice-Funktion „HelloWorld“ angelegt. Bereits jetzt kann man das Projekt starten (F5). Ist alles in Ordnung, startet ein Development-Webserver sowie ein Browser-Fenster. Klickt man auf den Link „Hello World“ erscheint ein automatisch generiertes Testfenster. Drückt man auf den Button „Aufrufen“, wird die WebService-Funktion „HelloWorld“ aufgerufen und das Ergebnis ( ein XML-Dokument im SOAP-Format ) angezeigt. Hurra.
Anmerkung 1: Sollte nach Start von F5 nicht gleich der HelloWorld-Webservice angezeigt werden, sondern eine Dateiauflistung, dann GuptaSoap.asmx anklicken.
Anmerkung 2: Eventuell auftauchende Messageboxen wg. „Web.Config“ oder dem „Namespace“ klicken wir einfach weg.

Einbinden des COM-Objekts

  • im Projektmappenexplorer per rechter Maustaste einen Verweis hinzufügen
  • unter „COM“ die GuptaCom 1.0 Type Library auswählen (Doppelklick)

In GuptaSoap.asmx.cs wird der eigentliche Code geschrieben:

[WebMethod]
 public ContactSaveResult ContactSave(String sFirstName, String sLastName, DateTime dtBirthday, Int32 nLuckyNumber)
 {} 

Die sog. Compiler-Direktive „[WebService]“ gibt an, dass die darauf folgend definierte Funktion als SOAP-Webservice „exportiert“ werden soll.

Die Webservicefunktion heißt ContactSave , nimmt die vier o.g. Parameter an und liefert ein Ergebnis in Form eines Structs zurück. Der Struct ist so definiert:

public struct ContactSaveResult
 {
  public Boolean bRet;
  public String sErrorMsg;
 }

Er besteht aus einem allgemeinen Returnwert bRet, der anzeigt, ob der Aufruf erfolgreich war. Ratsam ist außerdem eine möglichst aussagekräftige Fehlermeldung, die allen Beteiligten das Leben erleichtert. Die ganze Chose besteht  aus relativ vielen Komponenten (COM-Objekt, Gupta-Runtime, Datenbankanbindung und schließlich der Datenbank selbst); wenn auch nur eine davon streikt (bzw. falsch konfiguriert ist) schlägt der Aufruf fehl. In dem Fall ist es extrem hilfreich, anhand der Fehlermeldung die Ursache herausfinden zu können (ich spreche aus Erfahrung).

Die Funktion ContactSave(..) wird nun noch mit Leben gefüllt:

Zunächst wird der Return-Strukt instanziiert:

ContactSaveResult cResult = new ContactSaveResult();

Da das Instanziiern des COM-Objekts und der eigentliche Funktionsaufruf „unkontrolliert“ fehlschlagen kann (z.B. GuptaSoap wurde nicht registriert) fangen wir das in einem try-catch-Block ab:

try
 {
  GuptaCom.MyCom cGc = new GuptaCom.MyCom();  //instanziieren des COM-Objekts
  // der eigentliche Funktionsaufruf
  cResult.bRet = cGc.ContactSave(sFirstName, sLastName, dtBirthday, nLuckyNumber, ref cResult.sErrorMsg);
 }
 catch (Exception e)
 {
  cResult.bRet = false; // in jedem Fall war der Aufruf nicht erfolgreich
  cResult.sErrorMsg = e.Message; // die Exception gibt Auskunft über sich selbst. Die geben wir zurück
 }

Zu guter letzt geben wir den Return-Strukt zurück. Und das war’s.

return cResult;

Freundlicherweise stellt uns Visual-Studio gleich ein Testformular zur Verfügung, so dass wir uns nicht extra einen Applikation schreiben müssen, um den SOAP-Call in Aktion zu sehen. Einfach F5 und los geht’s.

Die einzige Voraussetzung ist, dass die SqlBase-Datenbank „ISLAND“ mit dem Standardlogin (User „sysadm“ PW „sysadm“ ) bereit steht. Ggf. könnt Ihr DB-Name und Login in der Funktion „TryConnectAndCheckDb(..)“ abändern. Grundsätzlich läuft es auch auf anderen DBMS (SqlServer, Oracle), allerdings muss das Creation-Skript für Tabelle und Index in eben dieser Funktion angepasst werden.

Have fun!

Hier alle Quellcodes zum Download:

GuptaCom.zip

GuptaSoap.zip

Von APD über COM nach SOAP – Teil 2

Im letzten Teil haben wir ein COM-Objekt in Gupta erzeugt. Nun wollen wir das aus einer anderen „Welt“ heraus aufrufen. Beispielhaft binden wir das Objekt in ein Excel-VBA-Programm ein (wir könnten natürlich auch Word, Access , Visual Studio etc. verwenden – entscheidend ist, dass eine Sprache verwendet wird, die COM-Objekte einbinden kann).

Das COM-Objekt

Wichtig ist mir zunächst, dass man Werte aus den gängigen Datentypen (Number, String und Date/Time) aus der Gupta-Welt in die VBA-Welt überträgt.  Also erstellen wir in unserem COM-Objekt vom letzten Mal (IMyCOM) eine Methode namens GetGuptaData(..).

Return:
Boolean
Parameter:
Number: nInput - als Datatype: VT_I4
Receive Number: nOutput - Datatype: VT_R8
Receive Date/Time: dtOutput
Receive String: sOutput
Code:
Set nOutput = 3.1415 * nInput
Set dtOutput = SalDateCurrent() + nInput
Set sOutput = SalNumberToStrX(nInput)
Return TRUE

Das Ganze als Inproc-COM-Server (DLL) kompilieren und – wichtig – einmal per Debug/Go laufen lassen. Dann wird das COM-Objekt in Windows registriert. Alternativ kann man auch per Commandline „regsvr32 GuptaCom.dll“ aufrufen.

Einbinden in Excel

Excel starten und via Extras/Makro/Visual Basic Editor selbigen öffnen. Dort unter Extras/Verweise in der Liste unser neu erstelltes COM-Objekt (GuptaCom 1.0 Type Library) ankreuzen und somit einbinden. Ab sofort können wir Objekte daraus instanziieren und deren Methoden aufrufen.

Und das geht z.B. so:  Einfügen / Modul

Dort den Programmcode eintragen:

Function Show() As Boolean
Rem Variablen deklarieren
Dim cMyCom As GuptaCom.MyCom
Dim nParameter As Integer
Dim nResult As Double
Dim dtResult As Date
Dim sResult As String
Dim bResult As Boolean
Rem Klasse instanziieren
Set cMyCom = CreateObject("GuptaCom.MyCom")
Rem Parameter aus aktueller Tabelle Zelle A1 abholen
nParameter = CInt(Worksheets(1).Range("B1").Value)
Rem Gupta-Funktion aufrufen
bResult = cMyCom.GetGuptaData(nParameter, nResult, dtResult, sResult)
If (bResult = True) Then
ActiveSheet.Range("B2").Value = "Funktionsaufruf erfolgreich"
ActiveSheet.Range("B3").Value = nResult
ActiveSheet.Range("B4").Value = dtResult
ActiveSheet.Range("B5").Value = sResult
Else
ActiveSheet.Range("B2").Value = "Fehler"
ActiveSheet.Range("B3").Value = ""
ActiveSheet.Range("B4").Value = ""
ActiveSheet.Range("B5").Value = ""
End If
Rem Returnwert zurückgeben
Show = bResult
End Function

Das Ganze speichern und zurück zur Excel-Tabelle. Über Ansicht/Symbolleisten/Steuerelement-Toolbox diese einblenden. Den Button wählen und auf’s Worksheet zeichnen. Mit „rechte Maustaste“/Eigenschaften den Button formatieren. „Rechte Maustaste“/Code anzeigen führt zur Programmstelle,  wo wir den Programmaufruf für das Click-Ereignis eintragen können. Z.B.:

Private Sub pbGetGuptaData_Click()
Call Modul1.Show
End Sub

Tabelle an sich noch etwas formatieren. Den Input-Parameter in Zelle B1 eintragen, die Ergebnisse des Funktionsaufrufs werden in B2:B5 ausgegebnen.
Ach ja – unter Extras/Makros/Sicherheit muss die Stufe Mittel oder Niedrig gewählt werden.

Jetzt kann aus Excel heraus Gupta-Programmcode aufgerufen werden.

Der oben beschriebene Beispielcode kann hier abgerufen werden: GuptaCom.zip

Kostenlose Quellcodeverwaltung für Visual C# Express 2010

Wenn man beruflich Software entwickelt, ist man es gewohnt, mit einer zentralen Quellcodeverwaltung zu arbeiten. Die Hauptvorteile sehe ich darin:

  • Der eigene wertvolle Code ist nicht nur auf der eigenen Platte, sondern auch im zentralen Repository.
  • Arbeitet man im Team an einem Projekt, kommt man um ein zentrales Repository eh nicht herum.

Im Büro nutzen wir den Team-Object-Manager für unsere Gupta-Projekte und Visual Source Safe für die VisualStudio-Projekte.
Ohne Quellcodeverwaltung fühle ich mich – ähnlich wie im Auto ohne Gurt – irgendwie nackt. Also musste für meine privaten Projekte nun endlich ein Repository her. Das sollte es können: Mit Visual C# Express 2010 umgehen können, möglichst nichts kosten, sich gut in die IDE einfügen und die Sourcefiles am besten gleich im Netz speichern.
Erste Recherchen im Netz legten nahe als Repository Subversion in Kombination mit TortoiseSVN zu verwenden. Subversion hatte einer unserer externen Entwickler vor einigen Wochen vorgestellt – scheint ganz gut zu sein. Wenn ich es richtig verstanden habe besteht dieses Framework aus drei Komponenten:

  1. Subversion Server – das Backend
  2. Subversion Client – kommandozeilenbasierter Client – kommuniziert mit dem Server via HTTP bzw. HTTPS
  3. TortoiseSVN – verknüpft quasi auf Betriebssystem-Ebene einzelne Dateiordner und Files mit dem Subversion Client

Den Subversion Client und TortoiseSVN kann man sich frei herunterladen. Als nächstes galt es, einen kostenlosen Subversion-Server zu finden. Nach oberflächlichen Recherchen hatte ich Sourceforge und unfuddle.com gefunden. Bei Sourceforge sind die Projekte offensichtlich alle öffentlich zugänglich, so dass ich mich für unfuddle.com entschieden habe. Dort kann man pro Account ein Projekt mit beliebige vielen Repositorys anlegen und hat maximal 200MB Plattenplatz zur Verfügung. Das sollte für meine Zwecke genügen.
Nun kam der etwas schwierigere Teil: Wie kann man die Quellcodeverwaltung in Visual C# Express 2010 integrieren? Meine Recherchen ergaben: Grundsätzlich gibt es in VS-Studio zwei Möglichkeiten, externe Tools einzubinden: Irgendwie richtig integrierte AddOns oder sog. externe Tools. Für die Express-Edition können diese AddOns leider nicht genutzt werden – das geht erst in den Professional-Editions. Also bleibt nur der Weg über die externen Tools. Fündig wurde ich im Blog von Gary Bodsworth (http://blog.programmerslog.com/?p=4). Er beschreibt dort die Integraton VS 2005 und 2008 und bietet die notwendigen Files zum Download an. Für Visual C# 2010 Express musste ich seine Datei ein wenig anpassen, was auf Anhieb geklappt hat.

Hier das Kochrezept:

  • Bei allen Installationen den Default-Ordner wählen – oder die SubversionMenuToolbarContextsVS2010.vssettings-Datei (s.u.) vor dem Import anpassen
  • Download und Installation eines Subversion-Clients (z.B. http://sliksvn.com/en/download/)
  • Download und Installation von TortoiseSVN http://tortoisesvn.net/downloads.html
  • Account bei unfuddle.com erstellen http://unfuddle.com/accounts/plans (z.B. „Private Free“)
  • Dort ein neues Repository anlegen (z.B. myfirstrepository). Den Link zum Repository merken (z.B. http://youraccountname.unfuddle.com/svn/youraccountname_myfirstrepository/) – kann man natürlich auch jederzeit nachschauen
  • Visual C# Express 2010 starten
  • dort im Menü „Tools/Settings/Expert Settings“ markieren
  • Menü „Tools/Settings/Import and Export Settings…“ wählen
  • dort „Import selected environment setting“ wählen und weiter
  • dort „Yes, save my current settings“ wählen (muss nicht, aber sicher ist sicher) und weiter
  • dort „Browse…“ und die Datei SubversionMenuToolbarContextsVS2010.vssettings wählen
  • die möglicherweise auftretenden Warnungen bedeuten meines Erachtens nur, dass durch die Erweiterung Executables aufgerufen werden, was potenziell gefährlich sein könnte. Natürlich wollen wir das und markieren die Checkboxen so lange, bis die Häkchen gesetzt sind.
  • klickt man nun auf „Finish“ sollte in der IDE: a) ein neues Menü namen Subversion sehen, b) eine Toolbar mit den selben Inhalten wie das neue Menü sehen. Des weiteren bekommt man Kontextmenüs bei den Quelldateien im Solution-Explorer zu sehen (später).
  • Unter dem neuen Menüpunkt „Subversion/Repository“ trägt man die URL von oben ein (http://youraccountname.unfuddle.com/svn/youraccountname_myfirstrepository/)
  • Alsdann kann man z.B. via Kontextmenü auf den Serverordner eigene Order oder Dateien hinzufügen, oder man lädt ein Projekt ins Studio und fügt es per „Subversion/Add Solution“ hinzu, oder, oder, oderWeitere Infos zu Subversion und Tortoise findet man auf deren Seiten http://subversion.apache.org/ und http://tortoisesvn.net

    Vielleicht noch die wichtigsten Menüpunkte in Kürze: „Subversion/Update“ holt Dateien aus dem Repository, „Subversion/Commit“ checkt sie ein.