WSDL- och tjänstkontrakt
Verktyget Wsutil.exe genererar en C-språkstub enligt angivna WSDL-metadata, samt definitioner och beskrivningar av datatyper som beskrivs av användarskapade XML-scheman.
Följande är ett exempel på ett WSDL-dokument och XML-schema som utgör grunden för den diskussion som följer:
<?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>
Det här exemplet innehåller ett kontrakt, ISimpleService, med en enda metod, SimpleMethod. "SimpleMethod" har två indataparametrar av typen heltal, en och b, som skickas från klienten till tjänsten. På samma sätt har SimpleMethod två utdataparametrar av typen heltal, b och c, som returneras till klienten efter slutförande. I SAL-kommenterad C-syntax visas metoddefinitionen på följande sätt:
void SimpleMethod(__in int a, __inout int * b, __out int * c );
I den här definitionen är ISimpleService ett tjänstkontrakt med en enda tjänståtgärd: SimpleMethod.
Utdatahuvudfilen innehåller definitioner och beskrivningar för extern referens. Detta inkluderar:
- C-strukturdefinitioner för globala elementtyper.
- En åtgärdsprototyp enligt definitionen i den aktuella filen.
- En funktionstabellprototyp för kontrakten som anges i WSDL-filen.
- Prototyper av klientproxy och tjänststub för alla funktioner som anges i den aktuella filen.
- En WS_ELEMENT_DESCRIPTION datastruktur för de globala schemaelement som definierats i den aktuella filen.
- En WS_MESSAGE_DESCRIPTION datastruktur för alla meddelanden som anges i den aktuella filen.
- En WS_CONTRACT_DESCRIPTION datastruktur för alla kontrakt som anges i den aktuella filen.
En global struktur genereras för att kapsla in alla globala beskrivningar för de schematyper och tjänstmodelltyper som programmet kan referera till. Strukturen namnges med ett normaliserat filnamn. I det här exemplet genererar Wsutil.exe en global definitionsstruktur med namnet "example_wsdl" som innehåller alla beskrivningar av webbtjänsten. Strukturdefinitionen genereras i stub-filen.
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 globala elementdefinitioner i XML-schemadokumentet (XSD) genereras en WS_ELEMENT_DESCRIPTION prototyp samt motsvarande C-typdefinition för vart och ett av elementen. Prototyperna för elementbeskrivningarna för SimpleMethod och SimpleMethodResponse genereras som medlemmar i strukturen ovan. C-strukturerna genereras på följande sätt:
typedef struct SimpleMethod
{
int a;
int b;
} SimpleMethod;
typedef struct SimpleMethodResponse
{
int b;
int c;
} SimpleMethodResponse;
På samma sätt för globala komplexa typer genererar Wsutil.exe typ C-strukturdefinitioner som ovan, utan matchande elementbeskrivningar.
För WSDL-indata genererar Wsutil.exe följande prototyper och definitioner:
- En WS_MESSAGE_DESCRIPTION prototyp genereras för meddelandebeskrivningen. Den här beskrivningen kan användas av tjänstmodellen och meddelandelagret. Strukturer för meddelandebeskrivning är fält med namnet "messagename" i den globala strukturen. I det här exemplet genereras meddelandebeskrivningen som fältet ISimpleService_SimpleMethod_InputMessage i ISimpleService_SimpleMethod_InputMessage struktur enligt vad som anges i WSDL-filen.
- WS_CONTRACT_DESCRIPTION prototyp genereras för kontraktsbeskrivningen. Den här beskrivningen används av tjänstmodellen. Kontraktsbeskrivningsstrukturer är fält med namnet "contractname" i den globala strukturen. I det här exemplet genereras kontraktsbeskrivningen som fältet DefaultBinding_ISimpleService i strukturen "_example_wsdl".
Specifikationer för åtgärd och typ är gemensamma för både proxy och stub och de genereras i båda filerna. Wsutil.exe genererar endast en kopia om både proxyn och stub genereras i samma fil.
Generering av identifierare
De autogenererade C-strukturerna som anges ovan skapas baserat på namnet som anges i WSDL-filen. En XML NCName betraktas vanligtvis inte som en giltig C-identifierare och namnen normaliseras efter behov. Hexvärden konverteras inte och vanliga bokstäver som ":", "/" och "." konverteras till understrecket '_' för att förbättra läsbarheten.
Sidhuvud för stub
För varje åtgärd i tjänstkontraktet genereras en återanropsrutin med namnet "<operationname>Callback". (Åtgärden "SimpleMethod" i exempeltjänstkontraktet har till exempel en genererad motringning med namnet "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 varje WSDL-portType genererar Wsutil.exe en funktionstabell som representerar portType-. Varje åtgärd på portType har en motsvarande funktionspekare till motringningen som finns i funktionstabellen.
struct ISimpleServiceMethodTable
{
ISimpleService_SimpleMethodCallback SimpleMethod;
};
Proxyprototyper genereras för alla åtgärder. Prototypnamnet är åtgärdsnamnet (i det här fallet "SimpleMethod") som anges i WSDL-filen för tjänstkontraktet.
HRESULT WINAPI SimpleMethod(WS_CHANNEL *channel,
WS_HEAP *heap,
int a,
int *b,
int *c,
const WS_ASYNC_CONTEXT * asyncContext,
WS_ERROR * error );
Prototypgenerering med endast lokal beskrivning
Proxy- och prenumerationsfilerna innehåller definitionen för den globala definitionsstrukturen, inklusive prototyper och definitioner för de strukturer som innehåller lokala beskrivningar och implementeringar av klientproxy/tjänststub.
Alla prototyper och definitioner som är lokala för stub-filen genereras som en del av en inkapslingsstruktur. Den här övergripande lokala beskrivningsstrukturen ger en tydlig hierarki med de beskrivningar som krävs av serialiseringsskiktet och tjänstmodellen. Den lokala beskrivningsstrukturen har prototyper som liknar den som visas nedan:
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;
Referera till definitioner från andra filer
Lokala definitioner kan referera till beskrivningar som genererats i en annan fil. Meddelandet kan till exempel definieras i C-kodfilen som genereras från WSDL-filen, men meddelandeelementet kan definieras någon annanstans i C-kodfilen som genereras från XSD-filen. I det här fallet genererar Wsutil.exe referens till det globala elementet från filen som innehåller meddelandedefinitionen, vilket visas nedan:
{ // WS_MESSAGE_DESCRIPTION
...
(WS_ELEMENT_DESRIPTION *)b_xsd.globalElement.<elementname>
};
Beskrivningar av globala element
För varje globalt element som definierats i en wsdl:type- eller XSD-fil finns det ett matchande fält med namnet elementName i fältet GlobalElement. I det här exemplet genereras en struktur med namnet SimpleMethod:
typedef struct _SimpleServiceLocal
{
struct // global elements
{
struct // SimpleMethod
{
...
WS_ELEMENT_DESCRIPTION SimpleMethod;
} SimpleMethod;
...
} globalElements;
}
Andra beskrivningar som krävs av elementbeskrivningen genereras som en del av den innehållande strukturen. Om elementet är ett enkelt typelement finns det bara ett WS_ELEMENT_DESCRIPTION fält. Om elementtypen är en struktur genereras alla relaterade fält och strukturbeskrivningar som en del av elementstrukturen. I det här exemplet är SimpleMethod-elementet en struktur som innehåller två fält, en och b. Wsutil.exe genererar strukturen på följande sätt:
...
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;
...
Inbäddade strukturer och inbäddade element genereras som understrukturer efter behov.
WSDL-relaterade definitioner
Wsutil.exe genererar ett fält under WSDL-avsnittet för vart och ett av portType- värden som definierats under den angivna wsdl:service.
...
struct { // WSDL
struct { // portTypeName
struct { // operationName
} operationName;
...
WS_OPERATION_DESCRIPTION* operations[numOperations];
WS_CONTRACT_DESCRIPTION contractDesc;
} portTypeName;
}
...
Wsutil.exe genererar ett fält f som innehåller alla beskrivningar som behövs för åtgärden, en teckenmatris med pekare till var och en av åtgärdsbeskrivningarna för varje metod och en WS_CONTRACT_DESCRIPTION för den angivna portType-.
Alla beskrivningar som krävs av åtgärder genereras i fältet operationName under den angivna portType-. Dessa inkluderar fältet WS_ELEMENT_DESCRIPTION samt understrukturen för indata- och utdataparametrar. På samma sätt ingår de WS_MESSAGE_DESCRIPTION fälten för indatameddelandet och det valfria utdatameddelandet tillsammans med; WS_PARAMETER_DESCRIPTION listfält för alla åtgärdsparametrar och fältet WS_OPERATION_DESCRIPTION för själva åtgärden. I det här exemplet genereras kodstrukturen för SimpleMethod-beskrivningen enligt nedan:
...
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;
...
XML-ordlisterelaterade definitioner
Namn och namnområden som används i olika beskrivningar genereras som fält av typen WS_XML_STRING. Alla dessa strängar genereras som en del av en konstant ordlista per fil. Listan över strängar och fältet WS_XML_DICTIONARY (med namnet diktat i exemplet nedan) genereras som en del av ordlistefältet i fileNameLocal struktur.
struct { // fileNameLocal
...
struct { // dictionary
struct { // XML string list
WS_XML_STRING firstFieldName;
WS_XML_STRING firstFieldNS;
...
} xmlStrings;
WS_XML_DICTIONARY dict;
} dictionary;
}; // fileNameLocal;
Matrisen med WS_XML_STRINGs genereras som en serie fält av typen WS_XML_STRING, med namn med användarvänliga namn. Den genererade stuben använder användarvänliga namn i olika beskrivningar för bättre läsbarhet.
Klientproxy för WSDL-åtgärder
Wsutil.exe genererar en klientproxy för alla åtgärder. Program kan skriva över metodsignaturen med hjälp av ett kommandoradsalternativ för prefix.
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
);
}
Åtgärdsanroparen måste skicka en giltig heap parameter. Utdataparametrar allokeras med hjälp av det WS_HEAP värde som anges i parametern heap. Den anropande funktionen kan återställa eller frigöra heapen för att frigöra minne för alla utdataparametrar. Om åtgärden misslyckas kan ytterligare information om felinformation hämtas från det valfria felobjektet om det är tillgängligt.
Wsutil.exe genererar en tjänststub för alla åtgärder som beskrivs i bindningen.
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 );
}
I avsnittet ovan beskrivs prototypen av den lokala strukturen som innehåller alla definitioner som är lokala för stub-filen. Följande avsnitt beskriver definitionerna av beskrivningarna.
WSDL-definitionsgenerering
Wsutil.exe genererar en konstant statisk (beständig statisk) struktur med namnet *<file_name>*LocalDefinitions av typen *<service_name>*Lokal som innehåller alla definitioner för endast lokalt.
const static _SimpleServiceLocal example_wsdlLocalDefinitions =
{
{ // global types
...
}, // global types
{ // global elements
...
}, // global elements
{ // messages
...
}, //messages
...
{ // dictionary
...
}, // dictionary
},
Följande WSDL-beskrivningar stöds:
- wsdl:service
- wsdl:binding
- wsdl:portType
- wsdl:operation
- wsdl:message
Bearbeta wsdl:operation och wsdl:message
Varje åtgärd som anges i WSDL-dokumentet mappas till en tjänståtgärd av Wsutil.exe. Verktyget genererar separata definitioner av tjänståtgärderna för både servern och klienten.
<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>
Layouten för dataelementen för indata och utflödesmeddelande utvärderas av verktyget för att generera serialiseringsmetadata för infrastrukturen tillsammans med den faktiska signaturen för den resulterande tjänståtgärden som indata- och utdatameddelandena är associerade till.
Metadata för varje åtgärd inom en specifik portType har indata och eventuellt ett utdatameddelande mappas vart och ett av dessa meddelanden till en WS_MESSAGE_DESCRIPTION. I det här exemplet ska indata och utdatameddelandet för åtgärden i portType mappas till inputMessageDescription och eventuellt outputMessageDescription på WS_OPERATION_DESCRIPTION respektive.
För varje WSDL-meddelande genererar verktyget WS_MESSAGE_DESCRIPTION som refererar till WS_ELEMENT_DESCRIPTION definition, vilket visas nedan:
...
{ // 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
...
Meddelandebeskrivningen refererar till beskrivningen av indataelementet. Eftersom elementet är globalt definierat refererar meddelandebeskrivningen till den globala definitionen i stället för det lokala statiska elementet. Om elementet definieras i en annan fil genererar Wsutil.exe på samma sätt en referens till den globalt definierade strukturen i filen. Om Till exempel SimpleMethodResponse definieras i en annan example.xsd-fil genererar Wsutil.exe följande i stället:
...
{ // 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
...
Varje meddelandebeskrivning innehåller åtgärden och den specifika elementbeskrivningen (ett fält av typen WS_ELEMENT_DESCRIPTION) för alla meddelandedataelement. När det gäller ett RPC-formatmeddelande eller ett meddelande med flera delar skapas ett wrapper-element för att kapsla in ytterligare information.
Stöd för RPC-format
Wsutil.exe stöder både dokumentformat och RPC-liknande åtgärder enligt WSDL 1.1-bindningstillägget för SOAP 1.2-specifikationen. Åtgärder i RPC- och literalstil markeras som WS_RPC_LITERAL_OPERATION. Tjänstmodellen ignorerar namnet på svarstextomslutningselementet i RPC/literalåtgärder.
Wsutil.exe har inte inbyggt stöd för kodningsliknande åtgärder. Parametern WS_XML_BUFFER genereras för kodning av meddelanden och utvecklare måste fylla i den täckande bufferten direkt.
Stöd för flera meddelandedelar
Wsutil.exe stöder flera meddelandedelar i ett meddelande. Ett meddelande i flera delar kan anges på följande sätt:
<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 genererar ett WS_STRUCT_TYPE fält för meddelandeelementet om meddelandet innehåller flera delar. Om meddelandet representeras med hjälp av dokumentformatet genererar Wsutil.exe ett omslutningselement med structtyp. Omslutningselementet har inget namn eller ett specifikt namnområde, och omslutningsstrukturen innehåller alla element i alla delar som fält. Omslutningselementet är endast för internt bruk och kommer inte att serialiseras i meddelandetexten.
Om meddelandet använder RPC- eller literalstilrepresentation skapar Wsutil.exe ett omslutningselement med åtgärdsnamnet som elementnamn och angivet namnområde som tjänstnamnområde enligt specifikationen för WSDL SOAP-tillägget. Strukturen för elementet innehåller en matris med fält som representerar de typer som anges i meddelandedelarna. Omslutningselementet mappas till det faktiska översta elementet i meddelandetexten enligt SOAP-specifikationen.
På serversidan resulterar varje åtgärd i en typedef av den resulterande servertjänståtgärden. Den här typedef används för att referera till åtgärden i funktionstabellen enligt beskrivningen tidigare. Varje åtgärd resulterar också i genereringen av en stub-funktion som nfrastructure anropar för ombudets räkning till den faktiska metoden.
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 SimpleMethod-åtgärden definieras SimpleMethodOperation typedef ovan. Observera att den genererade metoden har en utökad argumentlistamed meddelandedelen för in- och utdatameddelandet för SimpleMethod-åtgärden som namngivna parametrar.
På klientsidan mappas varje åtgärd till en proxytjänståtgärd.
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);
Bearbeta wsdl:binding
WWSAPI-tjänstmodellen stöderSOAP-bindningstillägget. För varje bindning finns det en associerad portType-.
Transporten som anges i soap-bindningstillägget är endast rådgivande. Programmet måste tillhandahålla transportinformation när du skapar en kanal. För närvarande stöder vi bindningar för WS_HTTP_BINDING och 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>
I vårt WSDL-exempeldokument har vi bara en portType- för ISimpleService. Den tillhandahållna SOAP-bindningen anger HTTP-transporten, som anges som WS_HTTP_BINDING. Observera att den här strukturen inte har statisk dekoration eftersom den här strukturen måste vara tillgänglig för programmet.
Bearbeta wsdl:portType
Varje portType- i WSDL består av en eller flera åtgärder. Åtgärden ska vara konsekvent med SOAP-bindningstillägget som anges i wsdl: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:portType name="ISimpleService">
<wsdl:operation name="SimpleMethod">
...
</wsdl:operation>
</wsdl:portType>
</wsdl:definitions>
I det här exemplet innehåller ISimpleService portType endast SimpleMethod-åtgärden. Detta överensstämmer med bindningsavsnittet där det bara finns en WSDL-åtgärd som mappar till en SOAP-åtgärd.
Eftersom ISimpleService portType bara har en åtgärd – SimpleMethod – innehåller motsvarande funktionstabell endast SimpleMethod som en tjänståtgärd.
När det gäller metadata mappas varje portType- av Wsutil.exe till en WS_CONTRACT_DESCRIPTION. Varje åtgärd i en portType- mappas till en WS_OPERATION_DESCRIPTION.
I det här exemplet genererar portType verktyget WS_CONTRACT_DESCRIPTION för ISimpleService. Den här kontraktsbeskrivningen innehåller det specifika antalet åtgärder som är tillgängliga på ISimpleService portType- tillsammans med en matris med WS_OPERATION_DESCRIPTION som representerar de enskilda åtgärder som definierats på portType för ISimpleService. Eftersom det bara finns en åtgärd på ISimpleService portType för ISimpleService finns det också bara en 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 ...
Bearbeta wsdl:service
WsUtil.exe använder tjänsterna för att hitta bindningar/porttyper och genererar kontraktsstruktur som beskriver typer, meddelande, porttypsdefinitioner och så vidare. Kontraktsbeskrivningar är externt tillgängliga och genereras som en del av den globala definitionsstruktur som anges via det genererade huvudet.
WsUtil.exe stöder EndpointReference-tillägg som definierats i wsdl:port. Slutpunktsreferens definieras i WS-ADDRESSING som ett sätt att beskriva slutpunkt information om en tjänst. Referenstilläggstexten för indataslutpunkten sparas som WS_XML_STRING, tillsammans med matchande WS_ENDPOINT_ADDRESS_DESCRIPTION genereras i avsnittet endpointReferences i den globala strukturen.
<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
}
Så här skapar du WS_ENDPOINT_ADDRESS med hjälp av WsUtil-genererade metadata:
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,
Konstanta strängar i klientproxyn eller tjänststub genereras som fält av typen WS_XML_STRING, och det finns en konstant ordlista för alla strängar i proxy- eller stub-filen. Varje sträng i ordlistan genereras som ett fält i ordlistans del av den lokala strukturen för bättre läsbarhet.
... // 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,
},
}
...
Bearbeta wsdl:type
Wsutil.exe stöder endast XSD-dokument (XML-schema) i specifikationen wsdl:type. Ett specialfall är när en meddelandeport anger en global elementdefinition. Mer information om de heuristiker som används i dessa fall finns i följande avsnitt.
Heuristik för parameterbearbetning
I tjänstmodellen mappas WSDL-meddelanden till specifika parametrar i en metod. Wsutil.exe har två typer av parametergenerering: i första format har åtgärden en parameter för indatameddelande och en parameter för utdatameddelande (om det behövs). i det andra formatet använder Wsutil.exe en heuristisk för att mappa och expandera fält i strukturerna för både indatameddelanden och utdatameddelanden till olika parametrar i åtgärden. Både indata- och utdatameddelanden måste ha meddelandeelement av strukturtyp för att generera den här andra metoden.
Wsutil.exe använder följande regler när du genererar åtgärdsparametrar från indata- och utdatameddelandena:
- För in- och utdatameddelanden med flera meddelandedelar är varje meddelandedel en separat parameter i åtgärden, med namnet på meddelandedelen som parameternamn.
- För RPC-formatmallsmeddelande med en meddelandedel är meddelandedelen en parameter i åtgärden med meddelandedelsnamnet som parameternamn.
- För in- och utdatameddelanden i dokumentformat med en meddelandedel:
- Om namnet på en meddelandedel är "parametrar" och elementtypen är en struktur, behandlas varje fält i strukturen som en separat parameter med fältnamnet som parameternamn.
- Om meddelandedelsnamnet inte är "parametrar" är meddelandet en parameter i åtgärden med det meddelandenamn som används som motsvarande parameternamn.
- För dokumentformatsindata och utdatameddelande med nillable-element mappas meddelandet till en parameter, med meddelandedelsnamnet som parameternamn. Ytterligare en indirekt nivå läggs till för att indikera att pekaren kan vara NULL-.
- Om ett fält endast visas i indatameddelandeelementet behandlas fältet som en [i]-parameter.
- Om ett fält endast visas i utdatameddelandeelementet behandlas fältet som en [out]-parameter.
- Om det finns ett fält med samma namn och samma typ som visas i både indatameddelandet och utdatameddelandet behandlas fältet som en [in,ut]-parameter.
Följande verktyg används för att fastställa parametrarnas riktning:
- Om ett fält endast visas i indatameddelandeelementet behandlas fältet som i endast parameter.
- Om ett fält endast visas i utdatameddelandeelementet behandlas fältet som en enda parameter.
- Om det finns ett fält med samma namn och samma typ som visas i både indatameddelandet och utdatameddelandet behandlas fältet som en in-,ut-parameter.
Wsutil.exe stöder endast sekvenserade element. Den avvisar ogiltig ordning när det gäller parametrarna [in,out] om Wsutil.exe inte kan kombinera parametrarna in och ut i en enskild parameterlista. Suffix kan läggas till i parameternamn för att undvika namnkollision.
<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 tar hänsyn till fält i tns:SimpleMethod och tns:SimpleMethodResponse ato som parametrar, enligt parameterdefinitionerna nedan:
<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 expanderar parameterlistan från fälten i listan ovan och genererar ParamStruct- struktur i följande kodexempel. Körningstiden för tjänstmodellen kan använda den här strukturen för att skicka argument till klienten och servern.
typedef struct SimpleMethodParamStruct {
unsigned int a;
unsigned int b;
unsigned int c;
} ;
Den här strukturen används bara för att beskriva stackramen på klient- och serversidan. Det finns ingen ändring i meddelandebeskrivningen, eller till de elementbeskrivningar som refereras till av meddelandebeskrivningen.
// 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
Som en allmän regel läggs en indirekt nivå till för alla parametrarna [out] och [in,out].
Parameterlös åtgärd
För dokument- och literalåtgärder behandlar Wsutil.exe åtgärden som att ha en indataparameter och en utdataparameter om:
- Indata- eller utdatameddelandet har mer än en del.
- Det finns bara en meddelandedel och namnet på meddelandedelen är inte "parametrar".
.. I exemplet ovan, förutsatt att meddelandedelarna heter ParamIn" och ParamOut, blir metodsignaturen följande kod:
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 genererar en versionssignatur för åtgärdsbeskrivningen så att WsCall- och tjänstmodellmotorn på serversidan kan kontrollera om den genererade beskrivningen gäller för den aktuella plattformen.
Den här versionsinformationen genereras som en del av WS_OPERATION_DESCRIPTION struktur. Versionsnumret kan behandlas som en unionsarmväljare för att göra strukturen utökningsbar. För närvarande är versionID- inställd på1 utan efterföljande fält. Framtida versiosn kan öka versionsnumret och inkludera fler fält efter behov. Till exempel genererar Wsutil.exe för närvarande följande kod baserat på versions-ID:t:
{ // 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
I framtiden kan den utökas på följande sätt:
WS_OPERATION_DESCRIPTION simpleMethodOperationDesc =
{
2,
&ISimpleService_SimpleMethod_InputputMessageDesc,
&ISimpleService_SimpleMethod_OutputMessageDesc,
WsCountOf(SimpleMethodParameters),
SimpleMethodParameters,
ISimpleService_SimpleMethod_Stub,
&forwardToString; // just as an example.
};
Säkerhet
Se avsnittet säkerhet i Wsutil Compiler-verktyget ämne.