Freigeben über


WSDL und Serviceverträge

Das Hilfsprogramm WsUtil.exe generiert einen C-Sprach-Stub gemäß den bereitgestellten WSDL-Metadaten sowie Datentypdefinitionen und Beschreibungen für Datentypen, die von vom Benutzer erstellten XML-Schemas beschrieben werden.

Im Folgenden finden Sie ein Beispiel für ein WSDL-Dokument und XML-Schema, das als Grundlage für die folgende Diskussion dient:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:types>
  <xs:schema xmlns:tns="http://Example.org" elementFormDefault="qualified" 
  targetNamespace="http://Example.org" xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:element name="SimpleMethod">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="a" type="xs:int" />
      <xs:element name="b" type="xs:int" />
     </xs:sequence>
    </xs:complexType>
   </xs:element>
   <xs:element name="SimpleMethodResponse">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="b" type="xs:int" />
      <xs:element name="c" type="xs:int" />
     </xs:sequence>
    </xs:complexType>
   </xs:element>
  </xs:schema>
 </wsdl:types>
 <wsdl:message name="ISimpleService_SimpleMethod_InputMessage">
  <wsdl:part name="parameters" element="tns:SimpleMethod" />
 </wsdl:message>
 <wsdl:message name="ISimpleService_SimpleMethod_OutputMessage">
  <wsdl:part name="parameters" element="tns:SimpleMethodResponse" />
 </wsdl:message>
 <wsdl:portType name="ISimpleService">
  <wsdl:operation name="SimpleMethod">
   <wsdl:input wsaw:Action="http://Example.org/ISimpleService/SimpleMethod" 
   message="tns:ISimpleService_SimpleMethod_InputMessage" />
   <wsdl:output wsaw:Action="http://Example.org/ISimpleService/SimpleMethodResponse" 
   message="tns:ISimpleService_SimpleMethod_OutputMessage" />
  </wsdl:operation>
 </wsdl:portType>
 <wsdl:binding name="DefaultBinding_ISimpleService" type="tns:ISimpleService">
  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
  <wsdl:operation name="SimpleMethod">
   <soap:operation soapAction="http://Example.org/ISimpleService/SimpleMethod" 
   style="document" />
   <wsdl:input>
    <soap:body use="literal" />
   </wsdl:input>
   <wsdl:output>
    <soap:body use="literal" />
   </wsdl:output>
  </wsdl:operation>
 </wsdl:binding>
 <wsdl:service name="SimpleService">
  <wsdl:port name="ISimpleService" binding="tns:DefaultBinding_ISimpleService">
   <soap:address location="http://Example.org/ISimpleService" />
  </wsdl:port>
 </wsdl:service>
</wsdl:definitions>

In diesem Beispiel wird ein Vertrag, ISimpleService, mit einer einzigen Methode, SimpleMethod, bereitgestellt. „SimpleMethod“ verfügt über zwei Eingabeparameter vom Typ integer, a und b, die vom Client an den Dienst gesendet werden. Ebenso verfügt SimpleMethod über zwei Ausgabeparameter vom Typ integer, b und c, die nach erfolgreichem Abschluss an den Client zurückgegeben werden. In der SAL-kommentierten C-Syntax wird die Methodendefinition wie folgt angezeigt:

void SimpleMethod(__in int a, __inout int *  b, __out int * c );

In dieser Definition ist ISimpleService ein Dienstvertrag mit einem einzelnen Dienstvorgang: SimpleMethod.

Die Ausgabeheaderdatei enthält Definitionen und Beschreibungen für externe Verweise. Dies umfasst u. a.:

  • C-Strukturdefinitionen für globale Elementtypen.
  • Ein Vorgangsprototyp, der in der aktuellen Datei definiert ist.
  • Ein Funktionstabellenprototyp für die in der WSDL-Datei angegebenen Verträge.
  • Clientproxy- und Dienst-Stubprototypen für alle in der aktuellen Datei angegebenen Funktionen.
  • Eine WS_ELEMENT_DESCRIPTION-Datenstruktur für die globalen Schemaelemente, die in der aktuellen Datei definiert sind.
  • Eine WS_MESSAGE_DESCRIPTION-Datenstruktur für alle Meldungen, die in der aktuellen Datei angegeben sind.
  • Eine WS_CONTRACT_DESCRIPTION-Datenstruktur für alle Verträge, die in der aktuellen Datei angegeben sind.

Eine globale Struktur wird generiert, um alle globalen Beschreibungen für die Schematypen und Dienstmodelltypen zu kapseln, auf die die Anwendung verweisen kann. Die Struktur wird mit einem normalisierten Dateinamen benannt. In diesem Beispiel generiert WsUtil.exe eine globale Definitionsstruktur namens „example_wsdl“, die alle Webdienstbeschreibungen enthält. Die Strukturdefinition wird in der Stubdatei generiert.

typedef struct _example_wsdl
{
  struct {
    WS_ELEMENT_DESCRIPTION SimpleMethod;
    WS_ELEMENT_DESCRIPTION SimpleMethodResponse;
  } elements;
  struct {
    WS_MESSAGE_DESCRIPTION ISimpleService_SimpleMethod_InputMessage;
    WS_MESSAGE_DESCRIPTION ISimpleService_SimpleMethod_OutputMessage;
  } messages;
  struct {
    WS_CONTRACT_DESCRIPTION DefaultBinding_ISimpleService;
  } contracts;
} _example_wsdl;

extern const _stockquote_wsdl stockquote_wsdl;

Für globale Elementdefinitionen im XML-Schemadokument (XSD) werden ein WS_ELEMENT_DESCRIPTION-Prototyp sowie die entsprechende C-Typdefinition für jedes Element generiert. Die Prototypen für die Elementbeschreibungen für SimpleMethod und SimpleMethodResponse werden als Mitglieder in der obigen Struktur generiert. Die C-Strukturen werden wie folgt generiert:

typedef struct SimpleMethod
{
  int   a;
  int   b;
} SimpleMethod;

typedef struct SimpleMethodResponse
{
  int   b;
  int   c;
} SimpleMethodResponse;

Auf gleiche Weise generiert WsUtil.exe für globale komplexe Typen Typ C-Strukturdefinitionen wie oben, ohne übereinstimmende Elementbeschreibungen.

Für WSDL-Eingabe generiert WsUtil.exe die folgenden Prototypen und Definitionen:

  • Ein WS_MESSAGE_DESCRIPTION-Prototyp wird für die Meldungsbeschreibung generiert. Diese Beschreibung kann sowohl vom Dienstmodell als auch von der Meldungsebene verwendet werden. Meldungsbeschreibungsstrukturen sind Felder namens „messagename“ in der globalen Struktur. In diesem Beispiel wird die Meldungsbeschreibung als ISimpleService_SimpleMethod_InputMessage-Feld in der ISimpleService_SimpleMethod_InputMessage-Struktur generiert, wie in der WSDL-Datei angegeben.
  • WS_CONTRACT_DESCRIPTION-Prototyp wird für die Vertragsbeschreibung generiert. Diese Beschreibung wird vom Dienstmodell verwendet. Vertragsbeschreibungsstrukturen sind Felder namens „contractname“ in der globalen Struktur. In diesem Beispiel wird die Vertragsbeschreibung als DefaultBinding_ISimpleService-Feld in der Struktur „_example_wsdl“ generiert.

Vorgangs- und Typspezifikationen gelten sowohl für Proxy als auch für Stub und werden in beiden Dateien generiert. WsUtil.exe generiert nur eine Kopie, wenn sowohl der Proxy als auch der Stub in derselben Datei generiert werden.

Generierung von Bezeichnern

Die oben aufgeführten automatisch generierten C-Strukturen werden basierend auf dem in der WSDL-Datei angegebenen Namen erstellt. Ein XML-NCName wird häufig nicht als gültiger C-Bezeichner betrachtet, und die Namen werden nach Bedarf normalisiert. Hexwerte werden nicht konvertiert, und allgemeine Zeichen wie „:“, „/“ und „.“ werden in den Unterstrich „_“ konvertiert, um die Lesbarkeit zu verbessern.

Kopfzeile für den Stub

Für jeden Vorgang im Dienstvertrag wird eine Rückrufroutine mit dem Namen „<operationname>Callback“ generiert. (Beispielsweise hat der Vorgang „SimpleMethod“ im Beispieldienstvertrag einen generierten Rückruf namens „SimpleMethodCallback“.)

typedef HRESULT (CALLBACK *SimpleMethodCallback) (
  const WS_OPERATION_CONTEXT * context,
  int a, int *b, int *c,
  const WS_ASYNC_CONTEXT *asyncContext,
  WS_ERROR * error);

Für jeden WSDL portType generiert WsUtil.exe eine Funktionstabelle, die für portType steht. Jeder Vorgang auf dem portType verfügt über einen entsprechenden Funktionszeiger auf den Rückruf, der in der Funktionstabelle vorhanden ist.

struct ISimpleServiceMethodTable
{
  ISimpleService_SimpleMethodCallback SimpleMethod;
};

Proxyprototypen werden für alle Vorgänge generiert. Der Prototypname ist der Vorgangsname (in diesem Fall „SimpleMethod“), der in der WSDL-Datei für den Dienstvertrag angegeben ist.

HRESULT WINAPI SimpleMethod(WS_CHANNEL *channel,
  WS_HEAP *heap,
  int a,
  int *b,
  int *c,
  const WS_ASYNC_CONTEXT * asyncContext,
  WS_ERROR * error );

Prototypgenerierung nur mit lokaler Beschreibung

Die Proxy- und Stub-Dateien enthalten die Definition für die globale Definitionsstruktur, einschließlich Prototypen und Definitionen für die Strukturen, die nur lokale Beschreibungen und Clientproxy-/Dienst-Stubimplementierungen enthalten.

Alle Prototypen und Definitionen, die lokal für die Stubdatei sind, werden als Teil einer gekapselten Struktur generiert. Diese übergeordnete lokale Beschreibungsstruktur bietet eine klare Hierarchie der Beschreibungen, die von der Serialisierungsebene und dem Dienstmodell benötigt werden. Die lokale Beschreibungsstruktur weist Prototypen auf, die dem unten gezeigten ähneln:

struct _filenameLocalDefinitions
{
  struct {
  // schema related output for all the embedded 
  // descriptions that needs to describe global complex types.
  } globalTypes;
  // global elements.
  struct {
  // schema related output, like field description
  // structure description, element description etc.
  ...
  } globalElements;
  struct {
  // messages and related descriptions
  } messages;
  struct {
  // contract and related descriptions.
  } contracts;
  struct {
  // XML dictionary entries.
  } dictionary;
} _filenameLocalDefinitions;

Verweisen auf Definitionen aus anderen Dateien

Lokale Definitionen können auf Beschreibungen verweisen, die in einer anderen Datei generiert wurden. Beispielsweise kann die Meldung in der aus der WSDL-Datei generierten C-Codedatei definiert werden, aber das Meldungselement kann an anderer Stelle in der aus der XSD-Datei generierten C-Codedatei definiert werden. In diesem Fall generiert WsUtil.exe einen Verweis auf das globale Element aus der Datei, die die Meldungsdefinition enthält, wie unten gezeigt:

{  // WS_MESSAGE_DESCRIPTION
...
(WS_ELEMENT_DESRIPTION *)b_xsd.globalElement.<elementname>
  };

Beschreibungen für globale Elemente

Für jedes globale Element, das in einer wsdl:type- oder XSD-Datei definiert ist, gibt es ein übereinstimmende Feld namens elementName im Feld GlobalElement. In diesem Beispiel wird eine Struktur mit dem Namen SimpleMethod generiert:

typedef struct _SimpleServiceLocal
{
  struct  // global elements
  {
    struct // SimpleMethod
    {
    ...
    WS_ELEMENT_DESCRIPTION SimpleMethod;
    } SimpleMethod;
    ...
  } globalElements;
}

Andere Beschreibungen, die von der Elementbeschreibung benötigt werden, werden als Teil der enthaltenden Struktur generiert. Wenn das Element ein einfaches Typelement ist, gibt es nur ein WS_ELEMENT_DESCRIPTION-Feld. Wenn der Elementtyp eine Struktur ist, werden alle verwandten Felder und Strukturbeschreibungen als Teil der Elementstruktur generiert. In diesem Beispiel ist das SimpleMethod-Element eine Struktur mit zwei Feldern, a und b. WsUtil.exe generiert die Struktur wie folgt:

...
struct // SimpleMethod
{
  struct // SimpleMethod structure
  {
    WS_FIELD_DESCRIPTION a;
    WS_FIELD_DESCRIPTION b;
    WS_FIELD_DESCRIPTION * SimpleMethodFields [2];
    WS_STRUCT_DESCRIPTION structDesc;
  } SimpleMethoddescs; // SimpleMethod
  WS_ELEMENT_DESCRIPTION elementDesc;
} SimpleMethod;
...

Eingebettete Strukturen und eingebettete Elemente werden nach Bedarf als Unterstrukturen generiert.

WsUtil.exe generiert ein Feld unter WSDL-Abschnitt für jeden portType-Wert, der unter dem angegebenen wsdl:service definiert ist.

...
struct { // WSDL
    struct { // portTypeName
        struct { // operationName
        } operationName;
    ...
    WS_OPERATION_DESCRIPTION* operations[numOperations];
    WS_CONTRACT_DESCRIPTION contractDesc;
    } portTypeName;
}
...

WsUtil.exe generiert ein Feld f, das alle Beschreibungen enthält, die für den Vorgang erforderlich sind, ein Signle-Array von Zeigern auf jede der Vorgangsbeschreibungen für jede Methode und eine WS_CONTRACT_DESCRIPTION für den angegebenen portType.

Alle Beschreibungen, die von Vorgängen benötigt werden, werden innerhalb des Felds operationName unter dem angegebenen portType generiert. Dazu gehören das WS_ELEMENT_DESCRIPTION-Feld sowie die Unterstruktur für Eingabe- und Ausgabeparameter. Ebenso werden die WS_MESSAGE_DESCRIPTION-Felder für die Eingabemeldung und die optionale Ausgabemeldung zusammen mit dem WS_PARAMETER_DESCRIPTION-Listenfeld für alle Vorgangsparameter und das WS_OPERATION_DESCRIPTION-Feld für den Vorgang selbst. In diesem Beispiel wird die Codestruktur für die SimpleMethod-Beschreibung wie unten dargestellt generiert:

...
struct // messages
{
  WS_MESSAGE_DESCRIPTION ISimpleService_SimpleMethod_InputMessage;
  WS_MESSAGE_DESCRIPTION ISimpleService_SimpleMethod_OutputMessage;
} messages;
struct // contracts
{
  struct // DefaultBinding_ISimpleService
  {
    struct // SimpleMethod
    {
      WS_PARAMETER_DESCRIPTION params[3];
      WS_OPERATION_DESCRIPTION SimpleMethod;
    } SimpleMethod;
    WS_OPERATION_DESCRIPTION* operations[1];
    WS_CONTRACT_DESCRIPTION contractDesc;
  } DefaultBinding_ISimpleService;
} contracts;
...

Namen und Namespaces, die in verschiedenen Beschreibungen verwendet werden, werden als Felder vom Typ WS_XML_STRING generiert. Alle diese Zeichenfolgen werden als Teil eines Konstantenwörterbuchs pro Datei generiert. Die Liste der Zeichenfolgen und das WS_XML_DICTIONARY-Feld (namens dict im folgenden Beispiel) werden als Teil des Wörterbuchfelds der fileNameLocal-Struktur generiert.

struct { // fileNameLocal
...
  struct { // dictionary
    struct { // XML string list
      WS_XML_STRING firstFieldName;
      WS_XML_STRING firstFieldNS;
      ...
    } xmlStrings;
  WS_XML_DICTIONARY dict;
  } dictionary;
}; // fileNameLocal;

Das Array von WS_XML_STRING wird als eine Reihe von Feldern vom Typ WS_XML_STRING generiert, die mit benutzerfreundlichen Namen benannt werden. Der generierte Stub verwendet die benutzerfreundlichen Namen in verschiedenen Beschreibungen zur besseren Lesbarkeit.

Clientproxy für WSDL-Vorgänge

WsUtil.exe generiert einen Clientproxy für alle Vorgänge. Anwendungen können die Methodensignatur mithilfe einer Befehlszeilenoption überschreiben.

HRESULT WINAPI bindingName_SimpleMethod(WS_SERVICE_PROXY *serviceProxy,
  WS_HEAP *heap,
  int a,
  int *b,
  int *c,
  const WS_CALL_PROPERTY* callProperties,
  ULONG callPropertyCount,
  const WS_ASYNC_CONTEXT * asyncContext,
  WS_ERROR * error )
{
  void* argList[] = {&a, &b, &c};
  return WsCall(_serviceProxy,
    (WS_OPERATION_DESCRIPTION*)&example_wsdlLocalDefinitions.contracts.DefaultBinding_ISimpleService.SimpleMethod.SimpleMethod,
    (void **)&_argList,
    callProperties,
    callPropertyCount,
    heap,
    asyncContext,
    error
  );      
}

Der Vorgangsaufrufer muss einen gültigen Heap-Parameter übergeben. Ausgabeparameter werden mithilfe des im Heap-Parameter angegebenen WS_HEAP-Werts zugewiesen. Die aufrufende Funktion kann den Heap zurücksetzen oder freigeben, um Speicher für alle Ausgabeparameter freizugeben. Wenn der Vorgang fehlschlägt, können zusätzliche Detailfehlerinformationen aus dem optionalen Fehlerobjekt abgerufen werden, wenn es verfügbar ist.

WsUtil.exe generiert einen Dienststub für alle Vorgänge, die in der Bindung beschrieben sind.

HRESULT CALLBACK ISimpleService_SimpleMethodStub(
  const WS_OPERATION_CONTEXT *context,
  void * stackStruct,
  void * callback,
  const WS_ASYNC_CONTEXT * asyncContext,
  WS_ERROR *error )
{
  SimpleMethodParamStruct *pstack = (SimpleMethodParamStruct *) stackstruct;
  SimpleMethodOperation operation = (SimpleMethodOperation)callback;
  return operation(context, pstack->a, &(pstack->b), &(pstack->c ), asyncContext, error );
}

Im obigen Abschnitt wird der Prototyp der lokalen Struktur beschrieben, die alle lokalen Definitionen nur für die Stubdatei enthält. In den nachfolgenden Abschnitten werden die Definitionen der Beschreibungen beschrieben.

Generierung der WSDL-Definition

WsUtil.exe generiert eine konstante statische (const static) Struktur namens *<file_name>*LocalDefinitions vom Typ *<service_name>*Local, die alle lokalen Definitionen enthält.

const static _SimpleServiceLocal example_wsdlLocalDefinitions =
{
  {  // global types
  ...
  }, // global types
  {  // global elements
  ...
  }, // global elements
  {  // messages
  ...
  }, //messages
  ...
  {  // dictionary
  ...
  }, // dictionary
},

Die folgenden WSDL-Beschreibungen werden unterstützt:

  • wsdl:service
  • wsdl:binding
  • wsdl:portType
  • wsdl:operation
  • wsdl:message

Verarbeiten von wsdl:operation und wsdl:message

Jeder im WSDL-Dokument angegebene Vorgang wird einem Dienstvorgang von WsUtil.exe zugeordnet. Das Tool generiert separate Definitionen der Dienstvorgänge sowohl für den Server als auch für den Client.

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:portType name="ISimpleService">
  <wsdl:operation name="SimpleMethod">
   <wsdl:input wsaw:Action="http://Example.org/ISimpleService/SimpleMethod" 
   message="tns:ISimpleService_SimpleMethod_InputMessage" />
   <wsdl:output wsaw:Action="http://Example.org/ISimpleService/SimpleMethodResponse" 
   message="tns:ISimpleService_SimpleMethod_OutputMessage" />
  </wsdl:operation>
 </wsdl:portType>
 <wsdl:message name="ISimpleService_SimpleMethod_InputMessage">
  <wsdl:part name="parameters" element="tns:SimpleMethod" />
 </wsdl:message>
 <wsdl:message name="ISimpleService_SimpleMethod_OutputMessage">
  <wsdl:part name="parameters" element="tns:SimpleMethodResponse" />
 </wsdl:message>
</wsdl:definitions>

Das Layout der Datenelemente für die Eingabe- und Ausgabemeldung wird vom Tool ausgewertet, um die Serialisierungsmetadaten für die Infrastruktur zusammen mit der tatsächlichen Signatur des resultierenden Dienstvorgangs zu generieren, dem die Eingabe- und Ausgabemeldungen zugeordnet sind.

Die Metadaten für jeden Vorgang innerhalb eines bestimmten portType-Elements verfügen über Eingabemeldungen und optional eine Ausgabemeldung. Jede dieser Meldungen wird einer WS_MESSAGE_DESCRIPTION zugeordnet. In diesem Beispiel sind die Eingabe- und die Ausgabemeldung für den Vorgang im portType-Objekt der inputMessageDescription und optional der outputMessageDescription für die WS_OPERATION_DESCRIPTION zugeordnet.

Für jede WSDL-Meldung generiert das Tool WS_MESSAGE_DESCRIPTION, die auf die WS_ELEMENT_DESCRIPTION-Definition verweist, wie unten dargestellt:

... 
{    // message description for ISimpleService_SimpleMethod_InputMessage
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.DefaultBinding_ISimpleServiceISimpleService_SimpleMethod_InputMessageactionName,
  (WS_ELEMENT_DESCRIPTION*)&(WS_ELEMENT_DESCRIPTION*)&example_wsdl.globalElements.SimpleMethodReponse
},  // message description for ISimpleService_SimpleMethod_InputMessage
...

Die Meldungsbeschreibung bezieht sich auf die Beschreibung des Eingabeelements. Da das Element global definiert ist, verweist die Meldungsbeschreibung auf die globale Definition anstatt auf das lokale statische Element. Wenn das Element in einer anderen Datei definiert ist, generiert WsUtil.exe einen Verweis auf die global definierte Struktur in dieser Datei. Wenn SimpleMethodResponse beispielsweise in einer anderen example.xsd-Datei definiert ist, generiert WsUtil.exe stattdessen Folgendes:

...
{    // message description for ISimpleService_SimpleMethod_InputMessage
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.DefaultBinding_ISimpleServiceISimpleService_SimpleMethod_InputMessageactionName,
(WS_ELEMENT_DESCRIPTION*)&(WS_ELEMENT_DESCRIPTION*)&example_xsd.globalElements.SimpleMethodReponse
},  // message description for ISimpleService_SimpleMethod_InputMessage
...

Jede Meldungsbeschreibung enthält die Aktion und die spezifische Elementbeschreibung (ein Feld vom Typ WS_ELEMENT_DESCRIPTION) für alle Meldungsdatenelemente. Im Fall einer Meldung im RPC-Format oder einer Meldung mit mehreren Teilen wird ein Wrapperelement erstellt, um die zusätzlichen Informationen zu kapseln.

Unterstützung für RPC-Stil

WsUtil.exe unterstützt Vorgänge im Dokumentstil sowie RPC-Stil gemäß der Spezifikation WSDL 1.1 Bindungserweiterung für SOAP 1.2. Vorgänge im RPC- und Literalstil werden als WS_RPC_LITERAL_OPERATION markiert. Das Dienstmodell ignoriert den Namen des Antworttext-Wrapperelements in RPC-/Literalvorgängen.

WsUtil.exe unterstützt keine Vorgänge im Codierungsstil. Der WS_XML_BUFFER-Parameter wird für die Codierung von Meldungen generiert, und Entwickler müssen den undurchsichtigen Puffer direkt auffüllen.

Unterstützung mehrerer Meldungsteile

WsUtil.exe unterstützt mehrere Meldungsteile in einer Meldung. Eine mehrteilige Meldung kann wie folgt angegeben werden:

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:message name="ISimpleService_MutipleParts_InputMessage">
  <wsdl:part name="part1" element="tns:SimpleElement1" />
  <wsdl:part name="part2" element="tns:SimpleElement2" />
 </wsdl:message>
</wsdl:definitions>

WsUtil.exe generiert ein WS_STRUCT_TYPE-Feld für das Meldungselement, wenn die Meldung mehrere Teile enthält. Wenn die Meldung mithilfe der Dokumentformatvorlage dargestellt wird, generiert WsUtil.exe ein Wrapperelement mit Strukturtyp. Das Wrapperelement hat keinen Namen oder einen bestimmten Namespace, und die Wrapperstruktur enthält alle Elemente in allen Teilen als Felder. Das Wrapperelement ist nur für die interne Verwendung vorgesehen und wird nicht im Meldungstext serialisiert.

Wenn die Meldung RPC- oder Literalformatdarstellung verwendet, erstellt WsUtil.exe ein Wrapperelement mit dem Vorgangsnamen als Elementnamen und dem angegebenen Namespace als Dienstnamespace gemäß der WSDL SOAP-Erweiterungsspezifikation. Die Struktur des Elements enthält ein Array von Feldern, die die in den Meldungsteilen angegebenen Typen darstellen. Das Wrapperelement wird dem tatsächlichen obersten Element im Meldungstext zugeordnet, wie in der SOAP-Spezifikation angegeben.

Auf Serverseite führt jeder Vorgang zu einer Typbeschreibung des resultierenden Serverdienstvorgangs. Diese Typdefinition wird verwendet, um wie zuvor beschrieben auf den Vorgang in der Funktionstabelle zu verweisen. Jede Operation führt auch zur Erzeugung einer Stub-Funktion, die nfrastructure im Namen des Delegierten der eigentlichen Methode aufruft.

typedef HRESULT (CALLBACK *SimpleMethodCallback) (
  const WS_OPERATION_CONTEXT* context,
  unsigned int  a,
  unsigned int * b,
  unsigned int * c,
  const WS_ASYNC_CONTEXT* asyncContext,
  WS_ERROR* error
  );

Für den SimpleMethod-Vorgang ist die SimpleMethodOperation-Typdefinition oben definiert. Beachten Sie, dass die generierte Methode über eine erweiterte Argumentliste mit dem Meldungsteil für die Eingabe- und Ausgabemeldung für den SimpleMethod-Vorgang als benannte Parameter verfügt.

Auf Clientseite wird jeder Vorgang einem Proxydienstvorgang zugeordnet.

HRESULT WINAPI SimpleMethod (
  WS_SERVICE_PROXY* serviceProxy,
  ws_heap *heap,
  unsigned int  a,
  unsigned int * b,
  unsigned int * c,
  const WS_ASYNC_CONTEXT* asyncContext,
  WS_ERROR* error);

Verarbeiten von wsdl:binding

Das WWSAPI-Dienstmodell unterstützt die SOAP-Bindungserweiterung. Für jede Bindung gibt es einen zugeordneten portType.

Der in der SOAP-Bindungserweiterung angegebene Transport ist nur eine Empfehlung. Die Anwendung muss beim Erstellen eines Kanals Transportinformationen bereitstellen. Derzeit unterstützen wir die Bindungen WS_HTTP_BINDING und WS_TCP_BINDING.

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:binding name="DefaultBinding_ISimpleService" type="tns:ISimpleService">
  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
  <wsdl:operation name="SimpleMethod">
   <soap:operation soapAction="http://Example.org/ISimpleService/SimpleMethod" 
   style="document" />
   <wsdl:input>
    <soap:body use="literal" />
   </wsdl:input>
   <wsdl:output>
    <soap:body use="literal" />
   </wsdl:output>
  </wsdl:operation>
 </wsdl:binding>
</wsdl:definitions>

In unserem WSDL-Beispieldokument haben wir nur einen portType für ISimpleService. Die bereitgestellte SOAP-Bindung gibt den HTTP-Transport an, der als WS_HTTP_BINDING angegeben wird. Beachten Sie, dass diese Struktur keine statische Dekoration aufweist, da diese Struktur für die Anwendung verfügbar sein muss.

Verarbeiten von wsdl:portType

Jeder portType in WSDL besteht aus einem oder mehreren Vorgängen. Der Vorgang sollte mit der SOAP-Bindungserweiterung konsistent sein, die in wsdl:binding angegeben ist.

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:portType name="ISimpleService">
  <wsdl:operation name="SimpleMethod">
   ...
  </wsdl:operation>
 </wsdl:portType>
</wsdl:definitions>

In diesem Beispiel enthält der ISimpleService portType nur den SimpleMethod-Vorgang. Dies entspricht dem Bindungsabschnitt, in dem nur ein WSDL-Vorgang vorhanden ist, der einer SOAP-Aktion zugeordnet ist.

Da der ISimpleService portType nur einen Vorgang hat – SimpleMethod – enthält die entsprechende Funktionstabelle nur SimpleMethod als Dienstvorgang.

In Bezug auf Metadaten wird jeder portType von WsUtil.exe einer WS_CONTRACT_DESCRIPTION zugeordnet. Jeder Vorgang innerhalb eines portType wird einer WS_OPERATION_DESCRIPTION zugeordnet.

In diesem Beispiel generiert portType die WS_CONTRACT_DESCRIPTION für ISimpleService. Diese Vertragsbeschreibung enthält die spezifische Anzahl von Vorgängen, die für den ISimpleService portType verfügbar sind, sowie ein Array von WS_OPERATION_DESCRIPTION, das die einzelnen Vorgänge darstellt, die für den portType für ISimpleService definiert sind. Da nur ein Vorgang auf ISimpleService portType für ISimpleService vorhanden ist, gibt es auch nur eine WS_OPERATION_DESCRIPTION-Definition.

...  part of LocalDefinitions structure
{    // array of operations for DefaultBinding_ISimpleService
(WS_OPERATION_DESCRIPTION*)&example_wsdlLocalDefinitions.contracts.DefaultBinding_ISimpleService.SimpleMethod.SimpleMethod,
},    // array of operations for DefaultBinding_ISimpleService
{    // contract description for DefaultBinding_ISimpleService
1,
(WS_OPERATION_DESCRIPTION**)example_wsdlLocalDefinitions.contracts.DefaultBinding_ISimpleService.operations,
WS_HTTP_CHANNEL_BINDING,
},  // end of contract description for DefaultBinding_ISimpleService
},    // DefaultBinding_ISimpleService       ...

Verarbeiten von wsdl:service

WsUtil.exe verwendet die Dienste, um Bindung/Porttypen zu finden, und generiert eine Vertragsstruktur, die Typen, Meldungen, Porttypdefinitionen usw. beschreibt. Vertragsbeschreibungen sind extern zugänglich und werden als Teil der globalen Definitionsstruktur generiert, die über generierten Header angegeben wird.

WsUtil.exe unterstützt EndpointReference-Erweiterungen, die in wsdl:port definiert sind. Endpunktreferenz wird in WS-ADDRESSING als eine Möglichkeit zum Beschreiben von Endpunkt-Informationen eines Diensts definiert. Der als WS_XML_STRING gespeicherte Text der Eingabeendpunktreferenzerweiterung wird zusammen mit der übereinstimmenden WS_ENDPOINT_ADDRESS_DESCRIPTION im Abschnitt „endpointReferences“ in der globalen Struktur generiert.

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:service name="SimpleService">
  <wsdl:port name="ISimpleService" binding="tns:DefaultBinding_ISimpleService">
   <soap:address location="http://Example.org/ISimpleService" />
   <wsa:EndpointReference>
    <wsa:Address>http://example.org/wcfmetadata/WSHttpNon</wsa:Address>
   </wsa:EndpointReference> 
  </wsdl:port>
 </wsdl:service>
</wsdl:definitions>
  const _example_wsdl example_wsdl =
  {
  ... // global element description
  {// messages
  {    // message description for ISimpleService_SimpleMethod_InputMessage
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.ISimpleService_SimpleMethod_InputMessageactionName,
  (WS_ELEMENT_DESCRIPTION*)&example_wsdl.globalElements.SimpleMethod,
},    // message description for ISimpleService_SimpleMethod_InputMessage
{    // message description for ISimpleService_SimpleMethod_OutputMessage
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.ISimpleService_SimpleMethod_OutputMessageactionName,
  (WS_ELEMENT_DESCRIPTION*)&example_wsdl.globalElements.SimpleMethodResponse,
},    // message description for ISimpleService_SimpleMethod_OutputMessage
}, // messages
{// contracts
{   // DefaultBinding_ISimpleService
1,
(WS_OPERATION_DESCRIPTION**)example_wsdlLocalDefinitions.contracts.DefaultBinding_ISimpleService.operations,
WS_HTTP_CHANNEL_BINDING,
},    // end of DefaultBinding_ISimpleService
    }, // contracts
    {
        {
            {   // endpointAddressDescription
                WS_ADDRESSING_VERSION_0_9,
            },                    
            (WS_XML_STRING*)&xml_string_generated_in_stub // endpointReferenceString
        }, //DefaultBinding_ISimpleService
    }, // endpointReferences
}

So erstellen Sie WS_ENDPOINT_ADDRESS mithilfe der generierten WsUtil-Metadaten:

WsCreateReader      // Create a WS_XML_READER
Initialize a WS_XML_READER_BUFFER_INPUT
WsSetInput          // Set the encoding and input of the reader to generate endpointReferenceString
WsReadType        // Read WS_ENDPOINT_ADDRESS from the reader
    // Using WS_ELEMENT_TYPE_MAPPING, WS_ENDPOINT_ADDRESS_TYPE and generated endpointAddressDescription, 

Konstantenzeichenfolgen im Clientproxy- oder Dienststub werden als Felder vom Typ WS_XML_STRING generiert, und es gibt ein Konstantenwörterbuch für alle Zeichenfolgen in der Proxy- oder Stubdatei. Jede Zeichenfolge im Wörterbuch wird als Feld im Wörterbuchteil der lokalen Struktur generiert, um eine bessere Lesbarkeit zu ermöglichen.

... // dictionary part of LocalDefinitions structure
{    // xmlStrings
  { // xmlStrings
    WS_XML_STRING_DICTIONARY_VALUE("a",&example_wsdlLocalDefinitions.dictionary.dict, 0), 
    WS_XML_STRING_DICTIONARY_VALUE("http://Sapphire.org",&example_wsdlLocalDefinitions.dictionary.dict, 1), 
    WS_XML_STRING_DICTIONARY_VALUE("b",&example_wsdlLocalDefinitions.dictionary.dict, 2), 
    WS_XML_STRING_DICTIONARY_VALUE("SimpleMethod",&example_wsdlLocalDefinitions.dictionary.dict, 3),
    ...
  },  // end of xmlStrings
  {   // SimpleServicedictionary
    // 45026280-d5dc-4570-8195-4d66d13bfa34
    { 0x45026280, 0xd5dc, 0x4570, { 0x81, 0x95, 0x4d,0x66, 0xd1, 0x3b, 0xfa, 0x34 } },
    (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings,
    stringCount,
    TRUE,
  },
}
...

Verarbeiten von wsdl:type

WsUtil.exe unterstützt nur XSD-Dokumente (XML Schema) in der wsdl:type-Spezifikation. Ein Sonderfall ist, wenn ein Meldungsport eine globale Elementdefinition angibt. Weitere Informationen zu den in diesen Fällen verwendeten Heuristiken finden Sie im folgenden Abschnitt.

Heuristiken für Parameterverarbeitung

Im Dienstmodell werden WSDL-Meldungen bestimmten Parametern in einer Methode zugeordnet. WsUtil.exe verfügt über zwei Formatvorlagen der Parametergenerierung: Im ersten Stil verfügt der Vorgang über einen Parameter für die Eingabemeldung und einen Parameter für die Ausgabemeldung (falls erforderlich); im zweiten Stil verwendet WsUtil.exe eine Heuristik zum Zuordnen und Erweitern von Feldern in den Strukturen für Eingabemeldungen und Ausgabemeldungen zu verschiedenen Parametern im Vorgang. Sowohl Eingabe- als auch Ausgabemeldungen müssen Strukturtypmeldungselemente aufweisen, um diesen zweiten Ansatz zu generieren.

WsUtil.exe verwendet die folgenden Regeln beim Generieren von Vorgangsparametern aus den Eingabe- und Ausgabemeldungen:

  • Bei Eingabe- und Ausgabemeldungen mit mehreren Meldungsteilen ist jeder Meldungsteil ein separater Parameter im Vorgang, wobei der Name des Meldungsteils als Parametername angegeben ist.
  • Bei Meldungen im RPC-Stil mit einem Meldungsteil ist der Meldungsteil ein Parameter im Vorgang, wobei der Name des Meldungsteils als Parametername angegeben ist.
  • Für Eingabe- und Ausgabemeldungen im Dokumentstil mit einem Meldungsteil:
    • Wenn der Name eines Meldungsteils „parameters“ lautet und der Elementtyp eine Struktur ist, wird jedes Feld in der Struktur als separater Parameter behandelt, wobei der Feldname der Parametername ist.
    • Wenn der Name des Meldungsteils nicht „parameters“ lautet, ist die Meldung ein Parameter im Vorgang mit dem Meldungsnamen, der als entsprechender Parametername verwendet wird.
  • Bei der Eingabe- und Ausgabemeldung im Dokumentstil mit einem nillable-Element wird die Meldung einem Parameter zugeordnet, wobei der Name des Meldungsteils als Parametername angegeben ist. Es wird eine zusätzliche Ebene der Indirektion hinzugefügt, um anzuzeigen, dass der Zeiger NULL sein kann.
  • Wenn ein Feld nur im Eingabemeldungselement angezeigt wird, wird das Feld als [in]-Parameter behandelt.
  • Wenn ein Feld nur im Ausgabemeldungselement angezeigt wird, wird das Feld als [out]-Parameter behandelt.
  • Wenn ein Feld mit demselben Namen und demselben Typ vorhanden ist, der sowohl in der Eingabemeldung als auch in der Ausgabemeldung angezeigt wird, wird das Feld als [in,out]-Parameter behandelt.

Die folgenden Tools werden verwendet, um die Richtung von Parametern zu bestimmen:

  • Wenn ein Feld nur im Eingabemeldungselement angezeigt wird, wird das Feld als [in only]-Parameter behandelt.
  • Wenn ein Feld nur im Ausgabemeldungselement angezeigt wird, wird das Feld als [out only]-Parameter behandelt.
  • Wenn ein Feld mit demselben Namen und demselben Typ vorhanden ist, der sowohl in der Eingabemeldung als auch in der Ausgabemeldung angezeigt wird, wird das Feld als [in,out]-Parameter behandelt.

WsUtil.exe unterstützt nur sequenzierte Elemente. Eine ungültige Sortierung in Bezug auf [in,out]-Parameter wird abgelehnt, wenn WsUtil.exe die Parameter nicht in einer einzigen Parameterliste kombinieren kann. Suffixe können Parameternamen hinzugefügt werden, um Namenskonflikte zu vermeiden.

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:message name="ISimpleService_SimpleMethod_InputMessage">
  <wsdl:part name="parameters" element="tns:SimpleMethod" />
 </wsdl:message>
 <wsdl:message name="ISimpleService_SimpleMethod_OutputMessage">
  <wsdl:part name="parameters" element="tns:SimpleMethodResponse" />
 </wsdl:message>
</wsdl:definitions>

WsUtil.exe berücksichtigt Felder in tns:SimpleMethod und tns:SimpleMethodResponse als Parameter, wie in den folgenden Parameterdefinitionen zu sehen:

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:types>
  <xs:schema xmlns:tns="http://Example.org" elementFormDefault="qualified" 
  targetNamespace="http://Example.org" xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:import namespace="http://Example.org" />
   <xs:element name="SimpleMethod">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="a" type="xs:unsignedInt" />
      <xs:element name="b" type="xs:unsignedInt" />
     </xs:sequence>
    </xs:complexType>
   </xs:element>
   <xs:element name="SimpleMethodResponse">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="b" type="xs:unsignedInt" />
      <xs:element name="c" type="xs:unsignedInt" />
     </xs:sequence>
    </xs:complexType>
   </xs:element>
  </xs:schema>
 </wsdl:types>
</wsdl:definitions>

WsUtil.exe erweitert die Parameterliste aus den Feldern in der obigen Liste und generiert die ParamStruct-Struktur im folgenden Codebeispiel. Die Laufzeit des Dienstmodells kann diese Struktur verwenden, um Argumente an die Client- und Serverstubs zu übergeben.

typedef struct SimpleMethodParamStruct {
  unsigned int   a;  
  unsigned int   b;
  unsigned int   c;
} ;

Diese Struktur wird nur verwendet, um den Stapelframe auf Client- und Serverseite zu beschreiben. Es gibt keine Änderung an der Meldungsbeschreibung oder an den Elementbeschreibungen, auf die von der Meldungsbeschreibung verwiesen wird.

  // following are local definitions for the complex type
  { // field description for a
  WS_ELEMENT_FIELD_MAPPING,
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aLocalName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
  WS_INT32_TYPE,
  0,
  WsOffsetOf(_SimpleMethod, a),
  0,
  0,
  },    // end of field description for a
  { // field description for b
  WS_ELEMENT_FIELD_MAPPING,
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.bLocalName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
  WS_INT32_TYPE,
  0,
  WsOffsetOf(_SimpleMethod, b),
  0,
  0,
  },    // end of field description for b
  {    // fields description for _SimpleMethod
  (WS_FIELD_DESCRIPTION *)&example_wsdlLocalDefinitions.globalElements.SimpleMethod._SimpleMethoddescs.a,
  (WS_FIELD_DESCRIPTION *)&example_wsdlLocalDefinitions.globalElements.SimpleMethod._SimpleMethoddescs.b,
  },
  {  // structure definition
  sizeof(_SimpleMethod),
  __alignof(_SimpleMethod),
  (WS_FIELD_DESCRIPTION**)&example_wsdlLocalDefinitions.globalElements.SimpleMethod._SimpleMethoddescs._SimpleMethodFields,
  WsCountOf(example_wsdlLocalDefinitions.globalElements.SimpleMethod._SimpleMethoddescs._SimpleMethodFields),
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings._SimpleMethodTypeName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
  0,
  },   // struct description for _SimpleMethod
  // following are global definitions for the out parameter
  ...
  {  // element description
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings._SimpleMethodTypeName,
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
  WS_STRUCT_TYPE,
  (void *)&example_wsdlLocalDefinitions.globalElements.SimpleMethod._SimpleMethoddescs.structDesc,
  },
  {    // message description for ISimpleService_SimpleMethod_InputMessage
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.ISimpleService_SimpleMethod_InputMessageactionName,
(WS_ELEMENT_DESCRIPTION*)&example_wsdl.globalElements.SimpleMethod,
  },    // message description for ISimpleService_SimpleMethod_InputMessage

In der Regel wird eine Ebene der Indirektion für alle [out]- und [in,out]-Parameter hinzugefügt.

Parameterloser Vorgang

Bei Dokument- und Literalvorgängen behandelt WsUtil.exe den Vorgang als einen Eingabeparameter und einen Ausgabeparameter, wenn:

  • Die Eingabe- oder Ausgabemeldung mehr als einen Teil aufweist.
  • Es nur einen Meldungsteil gibt und der Name des Meldungsteils nicht „parameters“ ist.

.. Im obigen Beispiel wird unter der Voraussetzung, dass die Meldungsteile ParamIn und ParamOut lauten, die Methodensignatur zum folgenden Code:

typedef struct SimpleMethod{
unsigned int a;
unsigned int b;
};

typedef struct SimpleMethodResponse {
unsigned int b;
unsigned int c;
};

typedef  struct ISimpleService_SimpleMethodParamStruct
{
SimpleMethod  * SimpleMethod;
SimpleMethodResponse  * SimpleMethodResponse;
} ISimpleService_SimpleMethodParamStruct;

WsUtil.exe generiert eine Versionssignatur für die Vorgangsbeschreibung, sodass das WsCall- und serverseitige Servicemodellmodul überprüfen kann, ob die generierte Beschreibung für die aktuelle Plattform anwendbar ist.

Diese Versionsinformationen werden als Teil der WS_OPERATION_DESCRIPTION-Struktur generiert. Die Versionsnummer kann als Union-Arm-Selektor behandelt werden, um die Struktur erweiterbar zu machen. Derzeit wird die versionID ohne nachfolgende Felder auf 1 festgelegt. Zukünftige Versionen können die Versionsnummer erhöhen und bei Bedarf weitere Felder einschließen. Beispielsweise generiert WsUtil.exe derzeit den folgenden Code basierend auf der Versions-ID:

{ // SimpleMethod
{ // parameter descriptions for SimpleMethod
{ WS_PARAMETER_TYPE_NORMAL, (USHORT)0, (USHORT)-1 },
{ WS_PARAMETER_TYPE_NORMAL, (USHORT)1, (USHORT)-1 },
{ WS_PARAMETER_TYPE_NORMAL, (USHORT)-1, (USHORT)1 },
},    // parameter descriptions for SimpleMethod
{    // operation description for SimpleMethod
1,
(WS_MESSAGE_DESCRIPTION*)&example_wsdl.messages.ISimpleService_SimpleMethod_InputMessage,
(WS_MESSAGE_DESCRIPTION*)&example_wsdl.messages.ISimpleService_SimpleMethod_OutputMessage,
3,
(WS_PARAMETER_DESCRIPTION*)example_wsdlLocalDefinitions.contracts.DefaultBinding_ISimpleService.SimpleMethod.params,
SimpleMethodOperationStub
}, //operation description for SimpleMethod
},  // SimpleMethod

In Zukunft könnte sie wie folgt erweitert werden:

WS_OPERATION_DESCRIPTION simpleMethodOperationDesc =
{
  2,
  &ISimpleService_SimpleMethod_InputputMessageDesc,
  &ISimpleService_SimpleMethod_OutputMessageDesc,
  WsCountOf(SimpleMethodParameters),
  SimpleMethodParameters,
  ISimpleService_SimpleMethod_Stub,
  &forwardToString;   // just as an example.
};

Sicherheit

Weitere Informationen finden Sie im Abschnitt „Sicherheit“ im Thema WsUtil-Compiler.