Sending Complex Types Using a Custom Type Mapper (Windows Embedded CE 6.0)
1/6/2010
A custom type mapper performs the following tasks:
- Turns XML into a valid COM data type, as in a VARIANT.
- Turns a COM data type, as in a VARIANT, into XML.
You create a custom type mapper based upon the complex types your application deals with. The SoapClient or SoapServer object then calls your custom type mapper when the object serializes or deserializes a specific complex type.
To send complex types in a SOAP message using a high-level API and a custom type mapper
Create a custom type mapper class that implements the ISoapTypeMapper interface.
Edit the Web Services Description Language (WSDL) file manually so you define the complex type; then use that complex type for the message part.
Edit the Web Services Meta Language (WSML) file to associate their custom type mapper with the complex type.
Modifying WSDL and WSML Files to Use the Type Mapper
If you use the WSDL/WSML Generator to create the WSDL and WSML files, you must manually modify these files to use the custom type mapper.
Note
The WSDL/WSML Generator is not included in SOAP Toolkit for Windows Embedded CE. You can use the generator from the desktop SOAP Toolkit 2.0.
When generating a WSDL file, the WSDL/WSML Generator specifies message parts as having the default type xsd:???????
if there is no corresponding XSD type for that part.
For example, the Addr complex type has no corresponding XSD type. Thus, the WSDL/WSML Generator specifies xsd:???????
for this complex type, as shown in bold in the following WSDL code example.
...
<types>
<schema targetNamespace='http://tempuri.org/type'
xmlns='http://www.w3.org/2001/XMLSchema'
xmlns:SOAP-ENC='https://schemas.xmlsoap.org/soap/encoding/'
xmlns:wsdl='https://schemas.xmlsoap.org/wsdl/'
elementFormDefault='qualified'>
</schema>
</types>
...
<message name='AddrBook.GetAddr'>
<part name='Name' type='xsd:string'/>
</message>
<message name='AddrBook.GetAddrResponse'>
<part name='Result' type='xsd:???????'/>
</message>
...
You must manually edit the WSDL file to replace all instances of the default type with a suitable type, and also to define the type.
In the case of the Addr complex type, editing the WSDL file results in the following definition (shown in bold) for that complex type.
...
<types>
<schema targetNamespace='http://tempuri.org/type'
xmlns='http://www.w3.org/2001/XMLSchema'
xmlns:SOAP-ENC='https://schemas.xmlsoap.org/soap/encoding/'
xmlns:wsdl='https://schemas.xmlsoap.org/wsdl/'
elementFormDefault='qualified'>
<complexType name="Addr">
<sequence>
<element name='name' type='string'/>
<element name='street' type='string'/>
<element name='city' type='string'/>
<element name='state' type='string'/>
<element name='zip-code' type='string'/>
</sequence>
</complexType>
</schema>
</types>
...
<message name='AddrBook.GetAddr'>
<part name='Name' type='xsd:string'/>
</message>
<message name='AddrBook.GetAddrResponse'>
<part name='Result' type='typens:Addr'/>
</message>
...
In addition to modifying the WSDL file, you must also modify the WSML file generated by the WSDL/WSML Generator. In the WSML file, you must associate the custom type mapper with the complex type.
Initially, the WSML file created by the WSDL/WSML Generator looks like the following code example. This initial file does not specify a custom type mapper, nor does it associate a complex type to a type mapper.
...
<using PROGID='AddrBookSvcRpcVb.AddrBook'
cachable='0'
ID='AddrBookObject' />
<port name='AddrBookSoapPort'>
<operation name='GetAddr'>
<execute uses='AddrBookObject'
method='GetAddr' dispID='1610809347'>
<parameter callIndex='1' name='Name' elementName='Name' />
<parameter callIndex='-1' name='retval' elementName='Result' />
</execute>
</operation>
</port>
...
The following code example shows how you would modify the initial WSML file so it specifies the AddrMapper custom type mapper and associates this type mapper to the Addr complex type.
...
<using PROGID='AddrBookSvcRpcVb.AddrBook'
cachable='0'
ID='AddrBookObject' />
<using PROGID='Addr.AddrMapper'
cachable='0'
ID='AddrMap' />
<types>
<type name='Addr'
targetNamespace='http://tempuri.org/type'
uses='AddrMap'
iid='{5A95BA3A-D30B-4D15-BBDF-9AF16E5A60BD}'/>
</types>
<port name='AddrBookSoapPort'>
<operation name='GetAddr'>
<execute uses='AddrBookObject'
method='GetAddr'
dispID='1610809347'>
<parameter callIndex='1' name='Name' elementName='Name' />
<parameter callIndex='-1' name='retval' elementName='Result' />
</execute>
</operation>
</port>
...
Note the use of the iid attribute on the <type> element. This attribute specifies the GUID of the interface object that represents the custom type that maps XML to objects.
You must specify the iid attribute for all complex types passed in an array. To determine the interface ID, check the interface IDL file.
See Also
Reference
ISoapTypeMapper
ISoapTypeMapperFactory