SOAP-Header definieren und verwenden

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Server mit Web-Service-Unterstützung schreiben

Die SOAP-Codierung einer Anforderung an eine Web-Service-Anwendung sowie der von der Anwendung gesendeten Antwort enthält einen Satz von Header-Knoten. Einige dieser Header wie z.B. der SOAP-Action-Header werden automatisch generiert und interpretiert. Sie können jedoch auch eigene Header definieren, um die Kommunikation zwischen dem Server und dessen Clients Ihren speziellen Anforderungen anzupassen. In der Regel enthalten derartige Header Informationen, die weniger die Methode als Objekt einer einzelnen Botschaft betreffen, sondern sich auf das gesamte aufrufbare Interface oder sogar die gesamte Anwendung beziehen.

Header-Klassen definieren

Für jeden neuen Header, den Sie definieren möchten, erstellen Sie eine von Soap.InvokeRegistry.TSOAPHeader abgeleitete Klasse. TSOAPHeader selbst ist ein Nachkomme von TRemotable. SOAP-Header-Objekte sind also nichts anderes als spezielle Arten von Remotable-Objekten. Wie bei jedem anderen Remotable-Objekt können Sie der von TSOAPHeader abgeleiteten Klasse neue published-Eigenschaften hinzufügen, welche die Informationen repräsentieren, welche der neue Header kommuniziert. Nachdem Sie die neue SOAP-Header-Klasse definiert haben, muss diese bei der Remotable-Typ-Registrierung eingetragen werden. Beachten Sie, dass Sie im Gegensatz zu anderen Remotable-Klassen für die Registrierung Ihrer Header-Typen explizit Code schreiben müssen.

TSOAPHeader definiert zwei Eigenschaften, die dazu verwendet werden, Attribute des SOAP-Header-Knotens zu repräsentieren. Diese Attribute heißen MustUnderstand und Actor. Wenn das MustUnderstand-Attribut den Wert True hat, muss der Empfänger einer Botschaft, die den Header enthält, in der Lage sein, diesen zu erkennen. Wenn der Empfänger einen Header bei gesetztem MustUnderstand-Attribut nicht interpretieren kann, muss er die Interpretation der gesamten Botschaft abbrechen. Eine Anwendung kann alle Header, die sie nicht erkennt, problemlos ignorieren, sofern deren MustUnderstand-Attribute nicht gesetzt sind. Die Handhabung von MustUnderstand wird durch die Actor-Eigenschaft näher bestimmt. Actor ist ein URI, der die Anwendung identifiziert, für welche der Header bestimmt ist. Wenn eine Web-Service-Anwendung beispielsweise Anforderungen zur weiteren Verarbeitung an einen anderen Dienst weiterleitet, können einige der Header in Client-Botschaften an jenen anderen Dienst gerichtet sein. Wenn diese Header das MustUnderstand-Attribut beinhalten, sollten Sie die Verarbeitung der Anforderung auch dann nicht abbrechen, wenn Ihre Anwendung die Header nicht interpretieren kann. Ihre Anwendung muss sich nur mit jenen Headern befassen, die als Actor die URL der Anwendung enthalten.

Header senden und empfangen

Nachdem Sie die Header-Klassen definiert und registriert haben, stehen diese Ihrer Anwendung zur Verfügung. Wenn Ihre Anwendung eine Anforderung empfängt, werden die Header der Botschaft automatisch in die entsprechenden Objekte der von Ihnen definierten, von TSOAPHeader abgeleiteten Klasse konvertiert. Die Anwendung identifiziert die entsprechende Header-Klasse, indem der Name des Header-Knotens mit dem Typnamen, der bei der Registrierung der Header-Klasse, oder mit dem Namen, der bei der Registrierung der Header-Klasse bei der Aufrufregistrierung verwendet wurde, verglichen wird. Alle Header, für welche die Anwendung keinen passenden Eintrag in der Remotable-Typ-Registrierung findet, werden ignoriert (oder die Anwendung generiert einen SOAP-Fehler, falls das MustUnderstand-Attribut des Headers auf True gesetzt ist).

Der Zugriff auf die von Ihrer Anwendung empfangenen Header ist mithilfe des Interface Soap.InvokeRegistry.ISOAPHeaders möglich. Dieses Interface kann auf zweierlei Arten erhalten werden: über eine Instanz von TInvokableClass oder – falls Sie Ihr aufrufbares Interface ohne Verwendung von TInvokableClass implementieren – durch einen Aufruf der globalen Funktion GetSOAPHeaders.

Mithilfe der Get-Methode von ISOAPHeaders greifen Sie auf die Header unter Angabe ihres Namens zu. Zum Beispiel:

 TServiceImpl.GetQuote(Symbol: string): Double;
 var
   Headers: ISOAPHeaders;
   H: TAuthHeader;
 begin
   Headers := Self as ISOAPHeaders;
   Headers.Get(AuthHeader, TSOAPHeader(H)); { Abrufen des Authentifizierungs-Headers }
   try
     if H = nil then
       raise ERemotableException.Create("SOAP header for authentication required");
     { Hier Code zur Überprüfung von Name und Kennwort einfügen }
   finally
     H.Free;
   end;
   { Nachdem der Benutzer authentifiziert ist, kann nachgeschlagen und ein Auszug zurückgegeben werden }
 end;

Wenn Sie Header in die Antwort aufnehmen möchten, die Ihre Anwendung in Reaktion auf eine Anforderungsbotschaft generiert, können Sie dies ebenfalls mithilfe des erwähnten Interface tun. ISOAPHeaders definiert eine Send-Methode, mit der Sie der ausgehenden Antwortbotschaft die gewünschten Header hinzufügen können. Zu diesem Zweck erzeugen Sie einfach für jeden Header, den Sie senden möchten, eine Instanz der entsprechenden Header-Klasse, setzen die Eigenschaften der Instanz entsprechend und rufen anschließend Send auf:

 TServiceImpl.GetQuote(Symbol: string): Double;
 var
   Headers: ISOAPHeaders;
   H: TQuoteDelay;
   TXSDuration Delay;
 begin
   Headers := Self as ISOAPHeaders;
   { Code zum Nachschlagen des Eintrags und Festlegen des Rückgabewerts }
   { Dieser Code setzt die Delay-Variable auf die Zeitverzögerung für den Auszug }
   H := TQuoteDelay.Create;
   H.Delay := Delay;
   Headers.OwnsSentHeaders := True;
   Headers.Send(H);
 end;

Header von Typ Skalar behandeln

Einige Web-Services definieren und verwenden einfache Header-Typen (z.B. Integer- oder String-Typen) und keine komplexen Strukturen, die Remotable-Typen entsprechen. Für die Unterstützung von SOAP-Headern in Delphi ist es aber erforderlich, dass Sie zur Repräsentation von Header-Typen einen Nachkommen von TSOAPHeader verwenden. Header-Klassen für einfache Typen können definiert werden, indem die Klasse TSOAPHeader als Container verwendet wird. Das heißt, dass der Nachkomme von TSOAPHeader eine einzige als published deklarierte Eigenschaft besitzt, die der Typ des eigentlichen Headers ist. Um anzuzeigen, dass die SOAP-Repräsentation keinen Knoten für den Nachkommen von TSOAPHeader enthalten muss, rufen Sie die Methode RegisterSerializeOptions der Remotable-Typregistrierung auf (nach der Registrierung des Header-Typs) und fügen Ihrem Header-Typ als Option xoSimpleTypeWrapper hinzu.

Struktur von Headern an andere Anwendungen übermitteln

Wenn Ihre Anwendung neue Header definiert, müssen Sie dafür sorgen, dass die Clients der Anwendung auf diese Definitionen Zugriff haben. Sofern die Clients ebenfalls in Delphi programmiert sind, können Sie die Unit, in der die Header-Klassen definiert und registriert werden, in die Client-Anwendung einbinden. Allerdings ist der Fall denkbar, dass Sie beabsichtigen, auch andere Clients über die von Ihnen verwendeten speziellen Header zu informieren. Um eine Anwendung in die Lage zu versetzen, Informationen über ihre Header-Klassen zu exportieren, müssen Sie die Header-Klassen bei der Aufruf-Registrierung bekannt machen. Durch die Registrierung einer Header-Klasse wird dieser Klasse auch ein Header-Name zugeordnet, der innerhabt eines Namespace definiert ist.

Ebenso wie der Code, der das aufrufbare Interface registriert, wird der Code zur Registrierung einer zu exportierenden Header-Klasse dem Initialisierungsabschnitt der Unit hinzugefügt, in der sie definiert ist. Mithilfe der globalen Funktion InvRegistry erhalten Sie eine Referenz auf die Aufruf-Registrierung, deren Methode RegisterHeaderClass Sie anschließend aufrufen, um das Interface anzugeben, mit dem der Header verknüpft ist:

 initialization
   InvRegistry.RegisterInterface(TypeInfo(IMyWebService)); { Registrieren des Interface }
   InvRegistry.RegisterHeaderClass(TypeInfo(IMyWebService), TMyHeaderClass); { und der Header-Klasse }
 end.
 static void RegTypes()
 {
   // Das aufrufbare Interface registrieren:
   InvRegistry()->RegisterInterface(__delphirtti(IMyService), "", "");
 // Zu verwendenden Header registrieren:
   InvRegistry()->RegisterHeaderClass(__delphirtti(IMyService), __classid(TMyHeader));
 }
 #pragma startup RegTypes 32

Sie können den Header auf eine Untermenge der Methoden des Interface durch nachfolgende Aufrufe der Methode RegisterHeaderMethod limitieren.

Hinweis:  Die uses-Klausel des Implementierungsabschnitts muss die Unit InvokeRegistry einschließen, damit der Aufruf an die Funktion InvRegistry definiert ist.

Sobald Sie die Header-Klasse bei der Aufruf-Registrierung eingetragen haben, wird die zugehörige Klassenbeschreibung beim Veröffentlichen des Web-Service den WSDL-Dokumenten automatisch hinzugefügt.

Hinweis:  Diese Anmeldung Ihrer Header-Klasse bei der Aufruf-Registrierung erfolgt zusätzlich zur Anmeldung jener Klasse bei der Remotable-Typ-Registrierung.

Siehe auch