WSDL- és szolgáltatási szerződések
A Wsutil.exe segédprogram a megadott WSDL-metaadatok alapján létrehoz egy C nyelvi csonkot, valamint adattípus-definíciókat és leírásokat a felhasználó által létrehozott XML-sémák által leírt adattípusokhoz.
Az alábbiakban egy példa WSDL-dokumentumot és XML-sémát mutatunk be, amely a következő vitafórum alapjául szolgál:
<?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>
Ez a példa egy ISimpleService nevű szerződést kínál egyetlen simpleMethod metódussal. A "SimpleMethod" két bemeneti paraméterrel rendelkezik, egész szám, egy és b, amelyeket az ügyfél küld a szolgáltatásnak. Hasonlóképpen, a SimpleMethod két kimeneti paraméterrel rendelkezik, egész szám, b és c, amelyeket a sikeres befejezés után a rendszer visszaad az ügyfélnek. A SAL-jegyzetekkel ellátott C szintaxisban a metódusdefiníció a következőképpen jelenik meg:
void SimpleMethod(__in int a, __inout int * b, __out int * c );
Ebben a definícióban az ISimpleService egy szolgáltatási szerződés egyetlen szolgáltatásművelettel: SimpleMethod.
A kimeneti fejlécfájl definíciókat és leírásokat tartalmaz külső hivatkozáshoz. Ez a következőket foglalja magában:
- C-struktúradefiníciók globális elemtípusokhoz.
- Az aktuális fájlban meghatározott műveleti prototípus.
- Függvénytábla prototípusa a WSDL-fájlban megadott szerződésekhez.
- Ügyfélproxy- és szolgáltatáscsomópont-prototípusok az aktuális fájlban megadott összes függvényhez.
- Az aktuális fájlban definiált globális sémaelemek WS_ELEMENT_DESCRIPTION adatstruktúrája.
- Egy WS_MESSAGE_DESCRIPTION adatstruktúra az aktuális fájlban megadott összes üzenethez.
- Egy WS_CONTRACT_DESCRIPTION adatstruktúra az aktuális fájlban megadott összes szerződéshez.
Egy globális struktúra jön létre, amely tartalmazza azoknak a sématípusoknak és szolgáltatásmodell-típusoknak a globális leírását, amelyekre az alkalmazás hivatkozhat. A struktúra neve normalizált fájlnévvel történik. Ebben a példában Wsutil.exe létrehoz egy "example_wsdl" nevű globális definíciós struktúrát, amely tartalmazza az összes webszolgáltatás-leírást. A struktúradefiníció a csonkfájlban jön létre.
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;
Az XML-sémadokumentum (XSD) globális elemdefinícióihoz egy WS_ELEMENT_DESCRIPTION prototípus, valamint a megfelelő C-típusdefiníció jön létre az egyes elemekhez. A SimpleMethod és a SimpleMethodResponse elemleírásainak prototípusai tagokként jönnek létre a fenti struktúrában. A C struktúrák a következőképpen jönnek létre:
typedef struct SimpleMethod
{
int a;
int b;
} SimpleMethod;
typedef struct SimpleMethodResponse
{
int b;
int c;
} SimpleMethodResponse;
A globális összetett típusokhoz hasonlóan a Wsutil.exe a fentihez hasonló C típusú struktúradefiníciókat hoz létre, elemleírások nélkül.
WSDL-bemenet esetén Wsutil.exe a következő prototípusokat és definíciókat hozza létre:
- A rendszer létrehoz egy WS_MESSAGE_DESCRIPTION prototípust az üzenet leírásához. Ezt a leírást a szolgáltatásmodell és az üzenetréteg is használhatja. Az üzenetleírási struktúrák a globális struktúra "messagename" nevű mezői. Ebben a példában az üzenet leírása a WSDL-fájlban megadott ISimpleService_SimpleMethod_InputMessage szerkezet ISimpleService_SimpleMethod_InputMessage mezőjeként jön létre.
- WS_CONTRACT_DESCRIPTION prototípus jön létre a szerződés leírásához. Ezt a leírást a szolgáltatásmodell használja. A szerződésleírási struktúrák a globális struktúra "contractname" nevű mezői. Ebben a példában a szerződés leírása a "_example_wsdl" struktúra DefaultBinding_ISimpleService mezőjeként jön létre.
A művelet- és típusspecifikációk a proxy és a csonk esetében is gyakoriak, és mindkét fájlban létrejönnek. Wsutil.exe csak akkor hoz létre egy másolatot, ha a proxy és a csonk is ugyanabban a fájlban jön létre.
Azonosító létrehozása
A fent felsorolt automatikusan létrehozott C struktúrák a WSDL-fájlban megadott név alapján jönnek létre. Az XML NCName általában nem tekinthető érvényes C-azonosítónak, és a nevek szükség szerint normalizálódnak. A hexa értékek nem lesznek konvertálva, és az olyan gyakori betűk, mint a ":", a "/" és a "." aláhúzásjeles "_" karakter lesznek konvertálva az olvashatóság javítása érdekében.
A csonk fejléce
A szolgáltatási szerződés minden egyes műveletéhez létre kell hozni egy "<műveletnév>Visszahívás" nevű visszahívási rutint. (A példában szereplő szolgáltatásszerződés "SimpleMethod" művelete például egy "SimpleMethodCallback" nevű visszahívást generált.)
typedef HRESULT (CALLBACK *SimpleMethodCallback) (
const WS_OPERATION_CONTEXT * context,
int a, int *b, int *c,
const WS_ASYNC_CONTEXT *asyncContext,
WS_ERROR * error);
Minden WSDL-portType Wsutil.exe létrehoz egy függvénytáblát, amely portType. A portType minden műveletéhez tartozik egy függvénymutató a függvénytáblában található visszahíváshoz.
struct ISimpleServiceMethodTable
{
ISimpleService_SimpleMethodCallback SimpleMethod;
};
A proxy prototípusok minden művelethez létre lesznek hozva. A prototípus neve a szolgáltatási szerződés WSDL-fájljában megadott műveletnév (ebben az esetben a "SimpleMethod").
HRESULT WINAPI SimpleMethod(WS_CHANNEL *channel,
WS_HEAP *heap,
int a,
int *b,
int *c,
const WS_ASYNC_CONTEXT * asyncContext,
WS_ERROR * error );
Csak helyi leírás prototípus létrehozása
A proxy- és asztub-fájlok tartalmazzák a globális definíciós struktúra definícióját, beleértve a csak helyi leírásokat és ügyfélproxy-/szolgáltatáscsomópont-implementációkat tartalmazó struktúrák prototípusait és definícióit.
A csonkfájlhoz tartozó összes prototípus és definíció egy beágyazó struktúra részeként jön létre. Ez az átfogó helyi leírási struktúra egyértelmű hierarchiát biztosít a szerializálási réteg és a szolgáltatásmodell által megkövetelt leírásokhoz. A helyi leírás struktúrája az alábbihoz hasonló prototípusokkal rendelkezik:
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;
Definíciók hivatkozása más fájlokból
A helyi definíciók hivatkozhatnak egy másik fájlban létrehozott leírásokra. Az üzenet definiálható például a WSDL-fájlból létrehozott C-kódfájlban, de az üzenetelem máshol is definiálható az XSD-fájlból létrehozott C-kódfájlban. Ebben az esetben Wsutil.exe az üzenetdefiníciót tartalmazó fájl globális elemére mutató hivatkozást hoz létre az alábbiak szerint:
{ // WS_MESSAGE_DESCRIPTION
...
(WS_ELEMENT_DESRIPTION *)b_xsd.globalElement.<elementname>
};
Globális elemleírások
A wsdl:type vagy XSD fájlban definiált összes globális elemhez tartozik egy elementName nevű mező a GlobalElement mezőben. Ebben a példában egy SimpleMethod nevű struktúra jön létre:
typedef struct _SimpleServiceLocal
{
struct // global elements
{
struct // SimpleMethod
{
...
WS_ELEMENT_DESCRIPTION SimpleMethod;
} SimpleMethod;
...
} globalElements;
}
Az elemleírás által megkövetelt egyéb leírások a tartalmazó szerkezet részeként jönnek létre. Ha az elem egyszerű típuselem, csak egy WS_ELEMENT_DESCRIPTION mező van. Ha az elemtípus egy struktúra, az összes kapcsolódó mező és szerkezetleírás az elemszerkezet részeként jön létre. Ebben a példában a SimpleMethod elem egy két mezőt tartalmazó struktúra, egy és b. Wsutil.exe az alábbiak szerint hozza létre a struktúrát:
...
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;
...
A beágyazott struktúrák és beágyazott elemek szükség szerint alstruktúrákként jönnek létre.
WSDL-hez kapcsolódó definíciók
Wsutil.exe létrehoz egy mezőt a WSDL szakaszban a megadott wsdl:szolgáltatásban meghatározott portType értékek mindegyikéhez.
...
struct { // WSDL
struct { // portTypeName
struct { // operationName
} operationName;
...
WS_OPERATION_DESCRIPTION* operations[numOperations];
WS_CONTRACT_DESCRIPTION contractDesc;
} portTypeName;
}
...
Wsutil.exe létrehoz egy f mezőt, amely tartalmazza a művelethez szükséges összes leírást, egy mutatótömböt az egyes metódusok műveletleírásaihoz, és egy WS_CONTRACT_DESCRIPTION a megadott portType.
A műveletekhez szükséges összes leírás a megadott portTypealatti operationName mezőben jön létre. Ezek közé tartozik a WS_ELEMENT_DESCRIPTION mező, valamint az s bemeneti és kimeneti paraméter alstruktúrája. Hasonlóképpen, a bemeneti üzenet WS_MESSAGE_DESCRIPTION mezői és az opcionális kimeneti üzenet is szerepelnie kell a; WS_PARAMETER_DESCRIPTION listamezőt az összes műveletparaméterhez és magának a műveletnek a WS_OPERATION_DESCRIPTION mezőjéhez. Ebben a példában a SimpleMethod leírás kódstruktúrája az alábbiak szerint jön létre:
...
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-szótárhoz kapcsolódó definíciók
A különböző leírásokban használt nevek és névterek WS_XML_STRINGtípusú mezőkként jönnek létre. Ezek a sztringek fájlonkénti állandó szótár részeként jönnek létre. A sztringek listája és a WS_XML_DICTIONARY mező (az alábbi példában diktálási) a fileNameLocal szerkezet szótármezőjének részeként jön létre.
struct { // fileNameLocal
...
struct { // dictionary
struct { // XML string list
WS_XML_STRING firstFieldName;
WS_XML_STRING firstFieldNS;
...
} xmlStrings;
WS_XML_DICTIONARY dict;
} dictionary;
}; // fileNameLocal;
A WS_XML_STRING-ek tömbje WS_XML_STRINGtípusú mezők sorozataként jön létre, felhasználóbarát névvel elnevezve. A létrehozott csonk különböző leírásokban a felhasználóbarát neveket használja a jobb olvashatóság érdekében.
Ügyfélproxy WSDL-műveletekhez
Wsutil.exe minden művelethez létrehoz egy ügyfélproxyt. Az alkalmazások felülírhatják a metódus aláírását egy előtag parancssori beállításával.
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
);
}
A művelethívónak érvényes halom paramétert kell megadnia. A kimeneti paraméterek a halom paraméterben megadott WS_HEAP értékkel vannak lefoglalva. A hívó függvény alaphelyzetbe állíthatja vagy felszabadíthatja a halomot, hogy felszabadítsa a memóriát az összes kimeneti paraméter számára. Ha a művelet sikertelen, további részletes hibainformációk kérhetők le az opcionális hibaobjektumból, ha elérhető.
Wsutil.exe létrehoz egy szolgáltatáscsomópontot a kötésben leírt összes művelethez.
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 );
}
A fenti szakasz a helyi struktúra prototípusát ismerteti, amely csak a csonkfájlhoz tartozó összes definíciót tartalmazza. A következő szakaszok a leírások definícióit ismertetik.
WSDL-definíció létrehozása
Wsutil.exe létrehoz egy * nevű állandó statikus (const static) struktúrát*<file_name>*LocalDefinitions típusú *<service_name>*Helyi, amely az összes csak helyi definíciót tartalmazza.
const static _SimpleServiceLocal example_wsdlLocalDefinitions =
{
{ // global types
...
}, // global types
{ // global elements
...
}, // global elements
{ // messages
...
}, //messages
...
{ // dictionary
...
}, // dictionary
},
A következő WSDL-leírások támogatottak:
- wsdl:service
- wsdl:binding
- wsdl:portType
- wsdl:operation
- wsdl:message
Wsdl:operation és wsdl:message feldolgozása
A WSDL-dokumentumban megadott összes művelet le van képezve egy szolgáltatásműveletre Wsutil.exe. Az eszköz külön definíciókat hoz létre a kiszolgáló és az ügyfél szolgáltatásműveleteihez.
<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>
A bemeneti és kimeneti üzenet adatelemeinek elrendezését az eszköz kiértékeli az infrastruktúra szerializálási metaadatainak létrehozásához, valamint az eredményül kapott szolgáltatásművelet tényleges aláírásához, amelyhez a bemeneti és kimeneti üzenetek társítva vannak.
Az egyes műveletek metaadatai egy adott portType bemenettel és opcionálisan kimeneti üzenettel is rendelkezik, ezek az üzenetek egy WS_MESSAGE_DESCRIPTIONvannak leképezve. Ebben a példában a portType műveletének bemenete és kimeneti üzenete az inputMessageDescription és opcionálisan az outputMessageDescription értékre van leképezve a WS_OPERATION_DESCRIPTION.
Minden WSDL-üzenethez az eszköz WS_MESSAGE_DESCRIPTION hoz létre, amely a WS_ELEMENT_DESCRIPTION definícióra hivatkozik az alábbiak szerint:
...
{ // 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
...
Az üzenet leírása a bemeneti elem leírására hivatkozik. Mivel az elem globálisan van definiálva, az üzenet leírása a helyi statikus elem helyett a globális definícióra hivatkozik. Hasonlóképpen, ha az elem egy másik fájlban van definiálva, Wsutil.exe létrehoz egy hivatkozást a fájl globálisan definiált szerkezetére. Ha például a SimpleMethodResponse egy másik example.xsd fájlban van definiálva, Wsutil.exe ehelyett a következőket hozza létre:
...
{ // 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
...
Minden üzenetleírás tartalmazza a műveletet és az adott elem leírását (egy WS_ELEMENT_DESCRIPTIONtípusú mezőt) az összes üzenetadat-elemhez. RPC-stílusú üzenet vagy több részből álló üzenet esetén egy burkolóelem jön létre a további információk beágyazásához.
RPC-stílus támogatása
Wsutil.exe támogatja a dokumentumstílust és az RPC-stílusú műveleteket a SOAP 1.2-specifikációhoz készült WSDL 1.1 kötésbővítménynek megfelelően. Az RPC- és a literál stílusú műveletek WS_RPC_LITERAL_OPERATION vannak megjelölve. A szolgáltatásmodell figyelmen kívül hagyja az RPC/literál műveletek válasz törzsburkoló elemének nevét.
Wsutil.exe nem támogatja natív módon a kódolási stílusú műveleteket. A WS_XML_BUFFER paraméter az üzenetek kódolásához jön létre, és a fejlesztőknek közvetlenül kell feltöltenie az átlátszatlan puffert.
Több üzenetrész támogatása
Wsutil.exe egy üzenet több üzenetrészét is támogatja. A többrészes üzenet a következőképpen adható meg:
<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 létrehoz egy WS_STRUCT_TYPE mezőt az üzenetelemhez, ha az üzenet több részt tartalmaz. Ha az üzenet a dokumentumstílus használatával van ábrázolva, Wsutil.exe létrehoz egy burkolóelemet, amely strukturált típust tartalmaz. A burkolóelem nem rendelkezik névvel vagy névtérrel, és a burkolószerkezet az összes rész összes elemét mezőként tartalmazza. A burkolóelem csak belső használatra készült, és nem lesz szerializálva az üzenet törzsében.
Ha az üzenet RPC- vagy konstansstílus-ábrázolásokat használ, Wsutil.exe létrehoz egy burkolóelemet, amelynek műveletneve az elem neve, a megadott névtér pedig szolgáltatásnévtérként a WSDL SOAP-bővítmény specifikációjának megfelelően. Az elem struktúrája egy mezőtömböt tartalmaz, amely az üzenetrészekben megadott típusokat jelöli. A burkolóelem az üzenet törzsének tényleges legfelső elemére van leképezve a SOAP specifikációban leírtak szerint.
A kiszolgálóoldalon minden művelet az eredményül kapott kiszolgálószolgáltatás-művelet típusdefef-ét eredményezi. Ez a típusdef a függvénytáblában szereplő műveletre hivatkozik a korábban leírtak szerint. Minden művelet egy csonkfüggvény létrehozását is eredményezi, amely a meghatalmazott nevében meghívja a tényleges metódust.
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
);
A SimpleMethod műveletnél a SimpleMethodOperation typedef definiálva van fent. Vegye figyelembe, hogy a létrehozott metódus bővített argumentumlistával rendelkezik, amely tartalmazza a SimpleMethod művelet bemeneti és kimeneti üzenetének üzenetrészét nevesített paraméterekként.
Az ügyféloldalon minden művelet proxyszolgáltatás-művelethez van leképezve.
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);
Wsdl:binding feldolgozása
A WWSAPI szolgáltatásmodell támogatja aSOAP kötésbővítményt. Minden kötéshez tartozik egy társított portType.
A szappankötési bővítményben megadott átvitel csak tanácsadás. Az alkalmazásnak átviteli adatokat kell megadnia egy csatorna létrehozásakor. Jelenleg támogatjuk a WS_HTTP_BINDING és WS_TCP_BINDING kötéseket.
<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>
A példa WSDL-dokumentumban csak egy portType az ISimpleService-hez. A megadott SOAP-kötés a HTTP-átvitelt jelzi, amely WS_HTTP_BINDING ként van megadva. Figyelje meg, hogy ez a szerkezet nem rendelkezik statikus díszítéssel, mivel ennek a szerkezetnek elérhetőnek kell lennie az alkalmazás számára.
Wsdl:portType feldolgozása
A WSDL minden portType egy vagy több műveletből áll. A műveletnek konzisztensnek kell lennie a soap kötési bővítményével, amely a wsdl:binding fájlban szerepel.
<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>
Ebben a példában az ISimpleService portType csak a SimpleMethod műveletet tartalmazza. Ez összhangban van a kötési szakaszsal, ahol csak egy WSDL-művelet van, amely SOAP-műveletre képez le.
Mivel az ISimpleService portType csak egy művelettel rendelkezik – SimpleMethod –, a megfelelő függvénytábla csak a SimpleMethod szolgáltatást tartalmazza.
A metaadatok tekintetében az egyes portType Wsutil.exe egy WS_CONTRACT_DESCRIPTIONképez le. A portType minden művelete egy WS_OPERATION_DESCRIPTIONvan leképezve.
Ebben a példában portType az eszköz WS_CONTRACT_DESCRIPTION hoz létre az ISimpleService-hez. Ez a szerződés leírása tartalmazza az ISimpleService portType elérhető műveletek konkrét számát, valamint egy WS_OPERATION_DESCRIPTION tömböt, amely az ISimpleService portType-ján meghatározott egyes műveleteket jelöli. Mivel csak egy művelet van az ISimpleService portType-on az ISimpleService-hez, csak egy WS_OPERATION_DESCRIPTION definíció van.
... 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 ...
Wsdl:service feldolgozása
WsUtil.exe a szolgáltatások használatával megkeresi a kötési/porttípusokat, és szerződésstruktúrát hoz létre, amely leírja a típusokat, az üzeneteket, a porttípus-definíciókat stb. A szerződésleírások külsőleg elérhetők, és a generált fejlécen keresztül megadott globális definíciós struktúra részeként jönnek létre.
WsUtil.exe támogatja a wsdl:portban definiált EndpointReference-bővítményeket. A végponthivatkozást a WS-ADDRESSING határozza meg, amely a szolgáltatás végpontjának információinak leírására szolgál. A bemeneti végpont hivatkozási bővítményének WS_XML_STRINGként mentett szövege és az egyező WS_ENDPOINT_ADDRESS_DESCRIPTION a globális struktúra EndpointReferences szakaszában jön létre.
<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
}
WS_ENDPOINT_ADDRESS létrehozása a WsUtil által létrehozott metaadatok használatával:
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,
Az ügyfélproxy vagy szolgáltatáscsomópont állandó sztringjei WS_XML_STRING típusú mezőkként jönnek létre, és a proxy vagy a csonkfájl összes sztringjének állandó szótára van. A szótár minden sztringje a helyi struktúra szótárrészének mezőjeként jön létre a jobb olvashatóság érdekében.
... // 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,
},
}
...
Wsdl feldolgozása:típus
Wsutil.exe csak az XML-séma (XSD) dokumentumait támogatja a wsdl:type specifikációban. Az egyik különleges eset az, amikor egy üzenetport globális elemdefiníciót ad meg. Az ezekben az esetekben használt heurisztika további részleteiért tekintse meg a következő szakaszt.
Paraméterfeldolgozási heurisztika
A szolgáltatásmodellben a WSDL-üzenetek egy metódus adott paramétereire vannak leképezve. Wsutil.exe kétféle paramétergenerálási stílussal rendelkezik: az első stílusban a művelet egy paramétert tartalmaz a bemeneti üzenethez, és egy paramétert a kimeneti üzenethez (ha szükséges); a második stílusban a Wsutil.exe heurisztikus használatával térképezi le és bontja ki a struktúrák mezőit mind a bemeneti üzenetek, mind a kimeneti üzenetek számára a művelet különböző paramétereire. A második megközelítés létrehozásához mind a bemeneti, mind a kimeneti üzeneteknek strukturált típusú üzenetelemekkel kell rendelkezniük.
Wsutil.exe a következő szabályokat használja, amikor műveleti paramétereket hoz létre a bemeneti és kimeneti üzenetekből:
- Több üzenetrészt tartalmazó bemeneti és kimeneti üzenetek esetén minden üzenetrész egy külön paraméter a műveletben, az üzenetrész neve paraméternévként.
- Az egy üzenetrészt tartalmazó RPC-stílusú üzenet esetében az üzenetrész a művelet egyik paramétere, az üzenetrész neve pedig paraméternév.
- Dokumentumstílusú beviteli és kimeneti üzenetek esetén egy üzenetrészlel:
- Ha egy üzenetrész neve "paraméterek", és az elemtípus egy struktúra, a rendszer a struktúra minden mezőjét külön paraméterként kezeli, és a mezőnév a paraméter neve.
- Ha az üzenetrész neve nem "paraméterek", akkor az üzenet a művelet egy paramétere, amelynek az üzenetneve a megfelelő paraméternév.
- Ha a dokumentumstílus-beviteli és kimeneti üzenet nem olvasható elemmel, az üzenet egy paraméterre van leképezve, az üzenetrész neve paraméternévként. Egy további indirekt szinttel jelzi, hogy a mutató lehet NULL.
- Ha egy mező csak a bemeneti üzenetelemben jelenik meg, a mező [in] paraméterként lesz kezelve.
- Ha egy mező csak a kimeneti üzenetelemben jelenik meg, a mező [out] paraméterként lesz kezelve.
- Ha a bemeneti üzenetben és a kimeneti üzenetben is ugyanazzal a névvel és típussal rendelkező mező jelenik meg, a mező [in,out] paraméterként lesz kezelve.
A paraméterek irányának meghatározásához a következő eszközök használhatók:
- Ha egy mező csak a bemeneti üzenetelemben jelenik meg, a mező csak paraméterként lesz kezelve.
- Ha egy mező csak a kimeneti üzenet elemében jelenik meg, a mező csak kimenő paraméterként lesz kezelve.
- Ha a bemeneti üzenetben és a kimeneti üzenetben is ugyanazzal a névvel és típussal rendelkező mező jelenik meg, a mező be- és kimenő paraméterként lesz kezelve.
Wsutil.exe csak a szekvenciált elemeket támogatja. Elutasítja az [in,out] paraméterekre vonatkozó érvénytelen rendezést, ha Wsutil.exe nem tudja egyetlen paraméterlistába egyesíteni a paramétereket és a paramétereket. A névütközések elkerülése érdekében utótagok is hozzáadhatók a paraméternevekhez.
<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 a tns:SimpleMethod és a tns:SimpleMethodResponse ato paramétermezőket veszi figyelembe, ahogyan az alábbi paraméterdefiníciókban látható:
<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 kibontja a paraméterlistát a fenti lista mezőiből, és létrehozza a ParamStruct struktúrát a következő kód példában. A szolgáltatásmodell futásideje ezzel a struktúrával argumentumokat adhat át az ügyfélnek és a kiszolgálócsomópontnak.
typedef struct SimpleMethodParamStruct {
unsigned int a;
unsigned int b;
unsigned int c;
} ;
Ez a struktúra csak az ügyfél- és kiszolgálóoldali veremkeret leírására szolgál. Nincs változás az üzenet leírásában vagy az üzenet leírásában hivatkozott elemleírásokban.
// 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
Általános szabályként az összes [out] és [in,out] paraméter esetében egy szintű közvetettség lesz hozzáadva.
Paraméter nélküli művelet
Dokumentum- és literálműveletek esetén Wsutil.exe úgy kezeli a műveletet, hogy egy bemeneti paramétert és egy kimeneti paramétert ad meg, ha:
- A bemeneti vagy kimeneti üzenet több részből áll.
- Csak egy üzenetrész van, és az üzenetrész neve nem "paraméterek".
.. A fenti példában feltételezve, hogy az üzenetrészek neve ParamIn" és ParamOut, a metódus aláírása a következő kód lesz:
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 létrehoz egy verzióazonosítót a művelet leírásához, így a WsCall és a kiszolgálóoldali szolgáltatásmodell motorja ellenőrizheti, hogy a létrehozott leírás alkalmazható-e az aktuális platformra.
Ez a verzióinformáció a WS_OPERATION_DESCRIPTION szerkezet részeként jön létre. A verziószám a struktúra bővíthetővé tétele érdekében egyesítő karválasztóként kezelhető. A versionID jelenleg 1 értékre van állítva, további mezők nélkül. A jövőbeli versiosn növelheti a verziószámot, és szükség szerint további mezőket is tartalmazhat. Például Wsutil.exe jelenleg a következő kódot hozza létre a verzióazonosító alapján:
{ // 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
A jövőben az alábbiak szerint bővíthető:
WS_OPERATION_DESCRIPTION simpleMethodOperationDesc =
{
2,
&ISimpleService_SimpleMethod_InputputMessageDesc,
&ISimpleService_SimpleMethod_OutputMessageDesc,
WsCountOf(SimpleMethodParameters),
SimpleMethodParameters,
ISimpleService_SimpleMethod_Stub,
&forwardToString; // just as an example.
};
Biztonság
Tekintse meg a Wsutil Compiler eszköz biztonsági szakaszát témakört.