WSDL dan Kontrak Layanan

Utilitas Wsutil.exe menghasilkan stub bahasa C sesuai dengan metadata WSDL yang disediakan, serta definisi dan deskripsi jenis data untuk jenis data yang dijelaskan oleh skema XML yang ditulis pengguna.

Berikut ini adalah contoh dokumen WSDL dan skema XML yang berfungsi sebagai dasar untuk diskusi yang mengikuti:

<?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>

Contoh ini menyediakan kontrak, ISimpleService, dengan satu metode, SimpleMethod. "SimpleMethod" memiliki dua parameter input bilangan bulat jenis, a dan b, yang dikirim dari klien ke layanan. Demikian juga, SimpleMethod memiliki dua parameter output bilangan bulat jenis, b dan c, yang dikembalikan ke klien setelah berhasil diselesaikan. Dalam sintaks C beranotasi SAL, definisi metode muncul sebagai berikut:

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

Dalam definisi ini, ISimpleService adalah kontrak layanan dengan satu operasi layanan: SimpleMethod.

File header output berisi definisi dan deskripsi untuk referensi eksternal. Drive ini termasuk:

  • Definisi struktur C untuk jenis elemen global.
  • Prototipe operasi seperti yang didefinisikan dalam file saat ini.
  • Prototipe tabel fungsi untuk kontrak yang ditentukan dalam file WSDL.
  • Proksi klien dan prototipe stub layanan untuk semua fungsi yang ditentukan dalam file saat ini.
  • Struktur data WS_ELEMENT_DESCRIPTION untuk elemen skema global yang ditentukan dalam file saat ini.
  • Struktur data WS_MESSAGE_DESCRIPTION untuk semua pesan yang ditentukan dalam file saat ini.
  • Struktur data WS_CONTRACT_DESCRIPTION untuk semua kontrak yang ditentukan dalam file saat ini.

Satu struktur global dihasilkan untuk merangkum semua deskripsi global untuk jenis skema dan jenis model layanan yang dapat dirujuk aplikasi. Struktur diberi nama menggunakan nama file yang dinormalisasi. Dalam contoh ini, Wsutil.exe menghasilkan struktur definisi global bernama "example_wsdl" yang berisi semua deskripsi layanan web. Definisi struktur dihasilkan dalam file stub.

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;

Untuk definisi elemen global dalam dokumen skema XML (XSD), satu prototipe WS_ELEMENT_DESCRIPTION , serta definisi jenis C yang sesuai, dihasilkan untuk setiap elemen. Prototipe untuk deskripsi elemen untuk SimpleMethod dan SimpleMethodResponse dihasilkan sebagai anggota dalam struktur di atas. Struktur C dihasilkan sebagai berikut:

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

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

Demikian pula untuk jenis kompleks global, Wsutil.exe menghasilkan definisi struktur tipe C seperti di atas, tanpa mencocokkan deskripsi elemen.

Untuk input WSDL, Wsutil.exe menghasilkan prototipe dan definisi berikut:

  • Prototipe WS_MESSAGE_DESCRIPTION dihasilkan untuk deskripsi pesan. Deskripsi ini dapat digunakan oleh model layanan serta lapisan pesan. Struktur deskripsi pesan adalah bidang bernama "messagename" dalam struktur global. Dalam contoh ini, deskripsi pesan dihasilkan sebagai bidang ISimpleService_SimpleMethod_InputMessage dalam struktur ISimpleService_SimpleMethod_InputMessage seperti yang ditentukan dalam file WSDL.
  • WS_CONTRACT_DESCRIPTION prototipe dihasilkan untuk deskripsi kontrak. Deskripsi ini digunakan oleh model layanan. Struktur deskripsi kontrak adalah bidang bernama "nama kontrak" dalam struktur global. Dalam contoh ini, deskripsi kontrak dihasilkan sebagai bidang DefaultBinding_ISimpleService dalam struktur "_example_wsdl".

Spesifikasi operasi dan jenis umum untuk proksi dan stub dan dihasilkan dalam kedua file. Wsutil.exe menghasilkan satu salinan hanya jika proksi dan stub dihasilkan dalam file yang sama.

Pembuatan pengidentifikasi

Struktur C yang dibuat secara otomatis yang tercantum di atas dibuat berdasarkan nama yang ditentukan dalam file WSDL. XML NCName umumnya tidak dianggap sebagai pengidentifikasi C yang valid, dan nama dinormalisasi sesuai kebutuhan. Nilai heks tidak dikonversi, dan huruf umum seperti ':', '/' dan '.' dikonversi ke karakter '_' garis bawah untuk meningkatkan keterbacaan.

Header untuk stub

Untuk setiap operasi dalam kontrak layanan, satu rutinitas panggilan balik bernama "<operationname>Callback" dihasilkan. (Misalnya, operasi "SimpleMethod" dalam contoh kontrak layanan memiliki panggilan balik yang dihasilkan bernama "SimpleMethodCallback".)

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

Untuk setiap WSDL portType Wsutil.exe menghasilkan tabel fungsi yang mewakili portType. Setiap operasi pada portType memiliki penunjuk fungsi yang sesuai dengan panggilan balik yang ada dalam tabel fungsi.

struct ISimpleServiceMethodTable
{
  ISimpleService_SimpleMethodCallback SimpleMethod;
};

Prototipe proksi dihasilkan untuk semua operasi. Nama prototipe adalah nama operasi (dalam hal ini, "SimpleMethod") yang ditentukan dalam file WSDL untuk kontrak layanan.

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

Pembuatan Prototipe Deskripsi Khusus Lokal

File proksi danstub berisi definisi untuk struktur definisi global, termasuk prototipe dan definisi untuk struktur yang berisi deskripsi khusus lokal dan implementasi proksi/layanan klien.

Semua prototipe dan definisi yang lokal ke file stub dihasilkan sebagai bagian dari struktur enkapsulasi. Struktur deskripsi lokal yang menyeluruh ini memberikan hierarki deskripsi yang jelas yang diperlukan oleh lapisan serialisasi dan model layanan. Struktur deskripsi lokal memiliki prototipe yang mirip dengan yang ditunjukkan di bawah ini:

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;

Mereferensikan definisi dari file lain

Definisi lokal dapat mereferensikan deskripsi yang dihasilkan dalam file lain. Misalnya, pesan dapat didefinisikan dalam file kode C yang dihasilkan dari file WSDL tetapi elemen pesan dapat didefinisikan di tempat lain dalam file kode C yang dihasilkan dari file XSD. Dalam hal ini, Wsutil.exe menghasilkan referensi ke elemen global dari file yang berisi definisi pesan, seperti yang ditunjukkan di bawah ini:

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

Deskripsi elemen global

Untuk setiap elemen global yang ditentukan dalam file wsdl:type atau XSD, ada bidang yang cocok bernama elementName di dalam bidang GlobalElement . Dalam contoh ini, struktur bernama SimpleMethod dihasilkan:

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

Deskripsi lain yang diperlukan oleh deskripsi elemen dihasilkan sebagai bagian dari struktur yang berisi. Jika elemen adalah elemen jenis sederhana, hanya ada satu bidang WS_ELEMENT_DESCRIPTION. Jika jenis elemen adalah struktur, semua bidang terkait dan deskripsi struktur dihasilkan sebagai bagian dari struktur elemen. Dalam contoh ini, elemen SimpleMethod adalah struktur yang berisi dua bidang, a dan b. Wsutil.exe menghasilkan struktur sebagai berikut:

...
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;
...

Struktur yang disematkan dan elemen yang disematkan dihasilkan sebagai sub-struktur sesuai kebutuhan.

Wsutil.exe menghasilkan bidang di bawah bagian WSDL untuk setiap nilai portType yang ditentukan di bawah wsdl:service yang ditentukan.

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

Wsutil.exe menghasilkan satu bidang f yang berisi semua deskripsi yang diperlukan untuk operasi, array penunjuk signle ke setiap deskripsi operasi untuk setiap metode, dan satu WS_CONTRACT_DESCRIPTION untuk portType yang ditentukan.

Semua deskripsi yang diperlukan oleh operasi dihasilkan di dalam bidang operationName di bawah portType yang ditentukan. Ini termasuk bidang WS_ELEMENT_DESCRIPTION serta sub-struktur untuk parameter input dan output. Demikian juga, bidang WS_MESSAGE_DESCRIPTION untuk pesan input dan pesan output opsional disertakan bersama dengan; WS_PARAMETER_DESCRIPTION bidang daftar untuk semua parameter operasi dan bidang WS_OPERATION_DESCRIPTION untuk operasi itu sendiri. Dalam contoh ini, struktur kode untuk deskripsi SimpleMethod dihasilkan seperti yang terlihat di bawah ini:

...
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;
...

Nama dan namespace yang digunakan dalam berbagai deskripsi dihasilkan sebagai bidang jenis WS_XML_STRING. Semua string ini dihasilkan sebagai bagian dari kamus konstanta per file. Daftar string dan bidang WS_XML_DICTIONARY (dict bernama dalam contoh di bawah) dihasilkan sebagai bagian dari bidang kamus struktur fileNameLocal.

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

Array WS_XML_STRINGdihasilkan sebagai serangkaian bidang jenis WS_XML_STRING, dinamai dengan nama yang mudah digunakan. Stub yang dihasilkan menggunakan nama yang mudah digunakan dalam berbagai deskripsi untuk keterbacaan yang lebih baik.

Proksi klien untuk operasi WSDL

Wsutil.exe menghasilkan proksi klien untuk semua operasi. Aplikasi dapat menimpa tanda tangan metode menggunakan opsi baris perintah awalan.

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
  );      
}

Pemanggil operasi harus meneruskan parameter heap yang valid. Parameter output dialokasikan menggunakan nilai WS_HEAP yang ditentukan dalam parameter heap . Fungsi panggilan dapat mengatur ulang atau membebaskan timbunan untuk melepaskan memori untuk semua parameter output. Jika operasi gagal, informasi kesalahan detail tambahan dapat diambil dari objek kesalahan opsional jika tersedia.

Wsutil.exe menghasilkan stub layanan untuk semua operasi yang dijelaskan dalam pengikatan.

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 );
}

Bagian di atas menjelaskan prototipe struktur lokal yang berisi semua definisi lokal ke file stub saja. Bagian berikutnya menjelaskan definisi deskripsi.

Pembuatan Definisi WSDL

Wsutil.exe menghasilkan struktur statis konstan (statis konstanta) bernama *<file_name>*LocalDefinitions tipe *<service_name>*Lokal yang berisi semua definisi lokal saja.

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

Deskripsi WSDL berikut ini didukung:

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

Memproses wsdl:operation dan wsdl:message

Setiap operasi yang ditentukan dalam dokumen WSDL dipetakan ke operasi layanan oleh Wsutil.exe. Alat ini menghasilkan definisi terpisah dari operasi layanan untuk server dan klien.

<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>

Tata letak elemen data pesan input danoutput dievaluasi oleh alat untuk menghasilkan metadata serialisasi untuk infrastruktur bersama dengan tanda tangan aktual dari operasi layanan yang dihasilkan tempat pesan input dan output dikaitkan.

Metadata untuk setiap operasi dalam portType tertentu memiliki pesan input dan output secara opsional, masing-masing pesan ini dipetakan ke WS_MESSAGE_DESCRIPTION. Dalam contoh ini, input dan pesan output pada operasi di portType dipetakan ke inputMessageDescription dan secara opsional outputMessageDescription pada WS_OPERATION_DESCRIPTION masing-masing.

Untuk setiap pesan WSDL alat menghasilkan WS_MESSAGE_DESCRIPTION yang mereferensikan definisi WS_ELEMENT_DESCRIPTION, seperti yang ditunjukkan di bawah ini:

... 
{    // 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
...

Deskripsi pesan mengacu pada deskripsi elemen input. Karena elemen didefinisikan secara global, deskripsi pesan mereferensikan definisi global alih-alih elemen statis lokal. Demikian pula, jika elemen didefinisikan dalam file lain, Wsutil.exe menghasilkan referensi ke struktur yang ditentukan secara global dalam file tersebut. Misalnya, jika SimpleMethodResponse didefinisikan dalam file example.xsd lain, Wsutil.exe menghasilkan yang berikut:

...
{    // 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
...

Setiap deskripsi pesan berisi tindakan dan deskripsi elemen tertentu (bidang jenis WS_ELEMENT_DESCRIPTION) untuk semua elemen data pesan. Dalam kasus pesan gaya RPC atau pesan dengan beberapa bagian, elemen pembungkus dibuat untuk merangkum informasi tambahan.

Dukungan gaya RPC

Wsutil.exe mendukung operasi gaya dokumen serta gaya RPC sesuai dengan WSDL 1.1 Binding Extension untuk spesifikasi SOAP 1.2. Operasi RPC dan gaya harfiah ditandai sebagai WS_RPC_LITERAL_OPERATION. Model layanan mengabaikan nama untuk elemen pembungkus isi respons dalam operasi RPC/literal.

Wsutil.exe tidak secara asli mendukung operasi gaya pengodean. Parameter WS_XML_BUFFER dihasilkan untuk mengodekan pesan, dan pengembang harus mengisi buffer buram secara langsung.

Dukungan beberapa bagian pesan

Wsutil.exe mendukung beberapa bagian pesan dalam satu pesan. Pesan multi-bagian dapat ditentukan sebagai berikut:

<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 menghasilkan bidang WS_STRUCT_TYPE untuk elemen pesan jika pesan berisi beberapa bagian. Jika pesan diwakili menggunakan gaya dokumen, Wsutil.exe menghasilkan elemen pembungkus dengan jenis struct. Elemen pembungkus tidak memiliki nama atau namespace tertentu, dan struktur pembungkus berisi semua elemen di semua bagian sebagai bidang. Elemen pembungkus hanya untuk penggunaan internal dan tidak akan diserialisasikan dalam isi pesan.

Jika pesan menggunakan RPC atau representasi gaya literal, Wsutil.exe membuat elemen pembungkus dengan nama operasi sebagai nama elemen dan namespace yang ditentukan sebagai namespace layanan sesuai dengan spesifikasi ekstensi WSDL SOAP. Struktur elemen berisi array bidang yang mewakili jenis yang ditentukan dalam bagian pesan. Elemen pembungkus dipetakan ke elemen teratas aktual dalam isi pesan seperti yang ditunjukkan dalam spesifikasi SOAP.

Di sisi server, setiap operasi menghasilkan typedef dari operasi layanan server yang dihasilkan. Typedef ini digunakan untuk merujuk ke operasi dalam tabel fungsi seperti yang dijelaskan sebelumnya. Setiap operasi juga menghasilkan pembuatan fungsi stub yang dipanggil nfrastructure atas nama delegasi ke metode aktual.

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
  );

Untuk operasi SimpleMethod, typedef SimpleMethodOperation ditentukan di atas. Perhatikan bahwa metode yang dihasilkan memiliki argumen yang diperluas dengan bagian pesan untuk pesan input dan output untuk operasi SimpleMethod sebagai parameter bernama.

Di sisi klien, setiap operasi dipetakan ke operasi layanan proksi.

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);

Memproses wsdl:binding

Model layanan WWSAPI mendukung ekstensi pengikatanSOAP. Untuk setiap pengikatan ada portType terkait.

Transportasi yang ditentukan dalam ekstensi pengikatan sabun hanya merupakan saran. Aplikasi perlu memberikan informasi transportasi saat membuat saluran. Saat ini kami mendukung pengikatan WS_HTTP_BINDING dan 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>

Dalam contoh dokumen WSDL kami, kami hanya memiliki satu portType untuk ISimpleService. Pengikatan SOAP yang disediakan menunjukkan transportasi HTTP, yang ditentukan sebagai WS_HTTP_BINDING. Perhatikan bahwa struktur ini tidak memiliki dekorasi statis karena struktur ini perlu tersedia untuk aplikasi.

Memproses wsdl:portType

Setiap portType di WSDL terdiri dari satu atau beberapa operasi. Operasi harus konsisten dengan ekstensi pengikatan SOAP yang ditunjukkan dalam 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>

Dalam contoh ini, ISimpleService portType hanya berisi operasi SimpleMethod. Ini konsisten dengan bagian pengikatan di mana hanya ada satu operasi WSDL yang memetakan ke tindakan SOAP.

Karena ISimpleService portType hanya memiliki satu operasi -- SimpleMethod -- tabel fungsi yang sesuai hanya berisi SimpleMethod sebagai operasi layanan.

Dalam hal metadata setiap portType dipetakan oleh Wsutil.exe ke WS_CONTRACT_DESCRIPTION. Setiap operasi dalam portType dipetakan ke WS_OPERATION_DESCRIPTION.

Dalam contoh ini, portType alat menghasilkan WS_CONTRACT_DESCRIPTION untuk ISimpleService. Deskripsi kontrak ini berisi jumlah operasi tertentu yang tersedia pada ISimpleService portType bersama dengan array WS_OPERATION_DESCRIPTION yang mewakili operasi individual yang ditentukan pada portType untuk ISimpleService. Karena hanya ada satu operasi pada ISimpleService portType untuk ISimpleService, hanya ada satu definisi WS_OPERATION_DESCRIPTION .

...  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       ...

Memproses wsdl:service

WsUtil.exe menggunakan layanan untuk menemukan pengikatan/porttype, dan menghasilkan struktur kontrak yang menjelaskan jenis, pesan, definisi porttype, dan sebagainya. Deskripsi kontrak dapat diakses secara eksternal, dan dihasilkan sebagai bagian dari struktur definisi global yang ditentukan melalui header yang dihasilkan.

WsUtil.exe mendukung ekstensi EndpointReference yang ditentukan dalam wsdl:port. Referensi titik akhir didefinisikan dalam WS-ADDRESSING sebagai cara untuk menjelaskan informasi titik akhir layanan. Teks ekstensi referensi titik akhir input disimpan sebagai WS_XML_STRING, bersama dengan WS_ENDPOINT_ADDRESS_DESCRIPTION yang cocok dihasilkan di bagian endpointReferences dalam struktur global.

<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
}

Untuk Membuat WS_ENDPOINT_ADDRESS menggunakan metadata yang dihasilkan WsUtil:

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, 

String konstanta dalam proksi klien atau stub layanan dihasilkan sebagai bidang jenis WS_XML_STRING, dan ada kamus konstan untuk semua string dalam file proksi atau stub. Setiap string dalam kamus dihasilkan sebagai bidang di bagian kamus struktur lokal untuk keterbacaan yang lebih baik.

... // 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,
  },
}
...

Memproses wsdl:type

Wsutil.exe hanya mendukung dokumen skema XML (XSD) dalam spesifikasi wsdl:type. Satu kasus khusus adalah ketika port pesan menentukan definisi elemen global. Lihat bagian berikut untuk detail selengkapnya tentang heuristik yang digunakan dalam kasus ini.

Heuristik Pemrosesan Parameter

Dalam model layanan, pesan WSDL dipetakan ke parameter tertentu dalam metode . Wsutil.exe memiliki dua gaya pembuatan parameter: dalam gaya pertama, operasi memiliki satu parameter untuk pesan input, dan satu parameter untuk pesan output (jika perlu); dalam gaya kedua, Wsutil.exe menggunakan heuristik untuk memetakan dan memperluas bidang dalam struktur untuk pesan input dan pesan output ke parameter yang berbeda dalam operasi. Pesan input dan output harus memiliki elemen pesan jenis struktur untuk menghasilkan pendekatan kedua ini.

Wsutil.exe menggunakan aturan berikut saat menghasilkan parameter operasi dari pesan input dan output:

  • Untuk pesan input dan output dengan beberapa bagian pesan, setiap bagian pesan adalah parameter terpisah dalam operasi, dengan nama bagian pesan sebagai nama parameter.
  • Untuk pesan gaya RPC dengan satu bagian pesan, bagian pesan adalah parameter dalam operasi, dengan nama bagian pesan sebagai nama parameter.
  • Untuk pesan input dan output gaya dokumen dengan satu bagian pesan:
    • Jika nama bagian pesan adalah "parameter" dan jenis elemen adalah struktur, setiap bidang dalam struktur diperlakukan sebagai parameter terpisah dengan nama bidang menjadi nama parameter.
    • Jika nama bagian pesan bukan "parameter", pesan adalah parameter dalam operasi dengan nama pesan yang digunakan sebagai nama parameter yang sesuai.
  • Untuk input gaya dokumen dan pesan output dengan elemen nillable, pesan dipetakan ke satu parameter, dengan nama bagian pesan sebagai nama parameter. Satu tingkat tidak langsung tambahan ditambahkan untuk menunjukkan penunjuk dapat berupa NULL.
  • Jika bidang hanya muncul di elemen pesan input, bidang diperlakukan sebagai parameter [in].
  • Jika bidang hanya muncul di elemen pesan output, bidang diperlakukan sebagai parameter [out].
  • Jika ada bidang dengan nama yang sama dan jenis yang sama yang muncul di pesan input dan pesan output, bidang diperlakukan sebagai parameter [in,out].

Alat berikut digunakan untuk menentukan arah parameter:

  • Jika bidang hanya muncul di elemen pesan input, bidang diperlakukan sebagai dalam parameter saja.
  • Jika bidang hanya muncul dalam elemen pesan output, bidang diperlakukan sebagai parameter keluar saja.
  • Jika ada bidang dengan nama yang sama dan jenis yang sama yang muncul di pesan input dan pesan output, bidang diperlakukan sebagai parameter masuk, keluar.

Wsutil.exe hanya mendukung elemen berurutan. Ini menolak pengurutan yang tidak valid sehubungan dengan parameter [in,out] jika Wsutil.exe tidak dapat menggabungkan parameter dalam dan parameter keluar ke dalam daftar parameter tunggal. Akhiran mungkin ditambahkan ke nama parameter untuk menghindari tabrakan nama.

<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 menganggap bidang dalam tns:SimpleMethod dan tns:SimpleMethodResponse sebagai parameter, seperti yang terlihat dalam definisi parameter di bawah ini:

<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 memperluas daftar parameter dari bidang dalam daftar di atas, dan menghasilkan struktur ParamStruct dalam contoh kode berikut. Run-time model layanan dapat menggunakan struktur ini untuk meneruskan argumen ke stub klien dan server.

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

Struktur ini hanya digunakan untuk menjelaskan bingkai tumpukan di sisi klien dan server. Tidak ada perubahan pada deskripsi pesan, atau ke deskripsi elemen yang dirujuk oleh deskripsi pesan.

  // 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

Sebagai aturan umum, satu tingkat tidak langsung ditambahkan untuk semua parameter [keluar] dan [masuk,keluar].

Operasi tanpa parameter

Untuk operasi dokumen dan literal, Wsutil.exe memperlakukan operasi sebagai memiliki satu parameter input dan satu parameter output jika:

  • Pesan input atau output memiliki lebih dari satu bagian.
  • Hanya ada satu bagian pesan dan nama bagian pesan bukan "parameter".

.. Dalam contoh di atas, dengan asumsi bagian pesan bernama ParamIn" dan ParamOut, tanda tangan metode menjadi kode berikut:

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 menghasilkan tanda tangan versi untuk deskripsi operasi sehingga mesin model layanan WsCall dan sisi server dapat memeriksa apakah deskripsi yang dihasilkan berlaku untuk platform saat ini.

Info versi ini dihasilkan sebagai bagian dari struktur WS_OPERATION_DESCRIPTION . Nomor versi dapat diperlakukan sebagai pemilih arm serikat untuk membuat struktur dapat diperluas. Saat ini, versionID diatur ke1 tanpa bidang berikutnya. Versiosn di masa mendatang dapat menambahkan nomor versi dan menyertakan lebih banyak bidang sesuai kebutuhan. Misalnya, Wsutil.exe saat ini menghasilkan kode berikut berdasarkan ID versi:

{ // 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

Di masa depan, ini dapat diperluas sebagai berikut:

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

Keamanan

Lihat bagian keamanan di topik alat Wsutil Compiler.