Übersicht über Dienstmodellebene

Die WWSAPI-Dienstmodell-API modelliert die Kommunikation zwischen einem Client und einem Dienst als Methodenaufrufe und nicht als Datennachrichten. Im Gegensatz zur Kanalebene, die den herkömmlicheren Nachrichtenaustausch zwischen Client und Dienst unterstützt, verwaltet das Dienstmodell die Kommunikation automatisch über einen Dienstproxy auf dem Client und einen Diensthost für den Dienst. Dies bedeutet, dass der Client generierte Funktionen aufruft und der Server Rückrufe implementiert.

Betrachten Sie beispielsweise einen Rechnerdienst, der eine Addition und Subtraktion für zwei Zahlen ausführt. Addition und Subtraktion sind Vorgänge, die natürlich als Methodenaufrufe dargestellt werden.

Diagramm, das zeigt, wie ein Rechnerdienst mit einem Client kommuniziert, indem Methodenaufrufe für Addition und Subtraktion verwendet werden.

Das Dienstmodell stellt die Kommunikation zwischen Client und Dienst als deklarierte Methodenaufrufe dar und verbirgt daher die Kommunikationsdetails der zugrunde liegenden Kanalebene vor der Anwendung, sodass der Dienst einfacher implementiert werden kann.

Angeben eines Diensts

Ein Dienst muss in Bezug auf seine Nachrichtenaustauschmuster sowie seine Netzwerkdatendarstellung angegeben werden. Für Dienste wird diese Spezifikation in der Regel als WSDL- und XML-Schemadokumente bereitgestellt.

Das WSDL-Dokument ist ein XML-Dokument, das die Kanalbindung und die Nachrichtenaustauschmuster des Diensts enthält, während das XML-Schemadokument ein XML-Dokument ist, das die Datendarstellung der einzelnen Nachrichten definiert.

Für den Rechnerdienst und seine Additions- und Subtraktionsvorgänge könnte das WSDL-Dokument wie im folgenden Beispiel aussehen:

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" 
xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" 
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsa10="http://www.w3.org/2005/08/addressing" 
xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:portType name="ICalculator">
  <wsdl:operation name="Add">
   <wsdl:input wsaw:Action="http://Example.org/ICalculator/Add" 
   message="tns:ICalculator_Add_InputMessage" />
   <wsdl:output wsaw:Action="http://Example.org/ICalculator/AddResponse" 
   message="tns:ICalculator_Add_OutputMessage" />
  </wsdl:operation>
 </wsdl:portType>
</wsdl:definitions>

Ebenso kann das XML-Schema wie folgt definiert werden:

<xs:schema xmlns:tns="http://Example.org" elementFormDefault="qualified" 
targetNamespace="http://Example.org" xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xs:element name="Add">
  <xs:complexType>
   <xs:sequence>
    <xs:element minOccurs="0" name="a" type="xs:int" />
    <xs:element minOccurs="0" name="b" type="xs:int" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>
 <xs:element name="AddResponse">
  <xs:complexType>
   <xs:sequence>
    <xs:element minOccurs="0" name="result" type="xs:int" 
    />
   </xs:sequence>
  </xs:complexType>
 </xs:element>
</xs:schema> 

Konvertieren von Metadaten in Code

Das Dienstmodell stellt die WsUtil.exe als Tool zum Verarbeiten dieser Metadatendokumente bereit, wobei eine WSDL-Datei in einen C-Header und Quelldateien konvertiert wird.

Diagramm, das zeigt, wie WsUtil.exe eine WSDL-Datei in einen C-Header und quelldateien konvertiert.

Die WsUtil.exe generiert Header und Quellen für die Dienstimplementierung sowie clientseitige Dienstvorgänge für den Client .

Aufrufen des Rechnerdiensts über einen Client

Wie bei der Dienstimplementierung muss der Client die generierten Header oder Header enthalten.

#include "CalculatorProxyStub.h"

Jetzt kann die Clientanwendung einen Dienstproxy erstellen und öffnen, um mit der Kommunikation mit dem Rechnerdienst zu beginnen.

WS_ENDPOINT_ADDRESS address = {0};
WS_STRING uri= WS_STRING_VALUE(L"http://localhost/example");
address.uri = uri;

if (FAILED (hr = WsCreateServiceProxy(WS_CHANNEL_TYPE_REQUEST, WS_HTTP_CHANNEL_BINDING, NULL, NULL, 0, &serviceProxy, error)))
    goto Error;

if (FAILED (hr = WsOpenServiceProxy(serviceProxy, &address, NULL, error)))
    goto Error;

Die Anwendung kann den Add-Vorgang für den Rechnerdienst mit dem folgenden Code aufrufen:

if (FAILED (hr = DefaultBinding_ICalculator_Add(serviceProxy, heap, 1, 2, &result, NULL, 0, NULL, error)))
    goto Error;

Eine vollständige Implementierung des Rechnerdiensts finden Sie im Codebeispiel unter HttpCalculatorClientExample .

Dienstmodellkomponenten

Die Interaktion der einzelnen WWSAPI-Dienstmodellkomponenten innerhalb des Rechnerbeispiels sieht wie folgt aus:

  • Der Client erstellt einen Dienstproxy und öffnet ihn.
  • Der Client ruft die Add-Funktion des Diensts auf und übergibt den Dienstproxy.
  • Die Nachricht wird gemäß den Serialisierungsmetadaten in den Header- und Quelldateien serialisiert, die vom Metadatentool (WsUtil.exe) generiert werden.
  • Die Nachricht wird in den Kanal geschrieben und über das Netzwerk an den Dienst übertragen.
  • Auf der Serverseite wird der Dienst in einem Diensthost gehostet und verfügt über einen Endpunkt, der auf den ICalculator-Vertrag lauscht.
  • Mithilfe der Dienstmodellmetadaten im Stub deserialisiert der Dienst die Nachricht vom Client und sendet sie an den Stub.
  • Der serverseitige Dienst ruft die Add-Methode auf und übergibt ihr den Vorgangskontext. Dieser Vorgangskontext enthält den Verweis auf die eingehende Nachricht.

Diagramm, das die Interaktion der einzelnen WWSAPI-Dienstmodellkomponenten zeigt.

Komponenten

  • Diensthost: Hostet einen Dienst.
  • Dienstproxy: Definiert, wie ein Client mit einem Dienst kommuniziert.
  • Kontext: Eigenschaftenbehälter zum Bereitstellen zustandsspezifischer Informationen für einen Dienstvorgang.
  • Vertrag: Die Schnittstellendefinition eines Diensts. ICalculator stellt beispielsweise einen Vertrag für den Rechnerdienst in unserem Beispielcode dar.
  • WsUtil.exe: Das Dienstmodell-Metadatentool zum Generieren von Proxys und Stubs.