New Features for PocketSOAP 1.5

SOAP 1.2 Support

Here's a quick sample of sending a SOAP 1.2 message with PocketSOAP, the changes from a PocketSOAP 1.4.3 usage are highlighted
dim env, t
set env = CreateObject("PocketSOAP.Envelope.12")
env.SetMethod "echoString", "http://example.org/ts-tests"
env.Parameters.Create "inputString", "Hello World"

set t = CreateObject("PocketSOAP.HTTPTransport")
t.Send "http://www.whitemesa.net/soap12/test-rpc", env
env.Parse t

wscript.echo env.Parameters.Item(1).Value

Note the 2 changes, first off, you use a different ProgID to create the envelope object, PocketSOAP.Envelope.12 will create a SOAP 1.2 envelope object, PocketSOAP.Envelope.11 will create a SOAP 1.1 envelope. the previously used PocketSOAP.Envelope.2 will continue to create a SOAP 1.1 envelope. Secondly, the envelope object is passed directly to the transport in the Send method, no longer do you pass a serialized instance of the envelope (i.e. you pass env, not env.serialize). This allows the transport to detect what version of SOAP envelope it is and send the correct Content-Type header in the request. If you do pass a serialized envelope to the Send method, then it will assume it is a SOAP 1.1 message (i.e. existing code should just continue to work without any changes).

The above sample generates this request

POST /soap12/test-rpc HTTP/1.1
Host: www.whitemesa.net
Accept-Charset: UTF-8, UTF-16;q=0.8, iso-8859-1;q=0.8
Accept-Encoding: deflate, gzip
Content-Type: application/soap+xml; charset="utf-8"
User-Agent: PocketSOAP/1.5.0/PocketHTTP/1.2.2
Content-Length: 380

<E:Envelope
	xmlns:a="http://example.org/ts-tests"
	xmlns:XS="http://www.w3.org/2001/XMLSchema"
	xmlns:XI="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:E="http://www.w3.org/2003/05/soap-envelope">
	<E:Body>
	<a:echoString E:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
	<inputString XI:type="XS:string">Hello World</inputString>
	</a:echoString>
	</E:Body></E:Envelope>

gzip compression

In addition to the existing support for deflate compression, gzip compression is now also supported. By default the request will indicate that it supports both deflate and gzip'd responses. If you are sending compressed requests, then these will continue to be deflate compressed by default, if you want to send a gzip compressed request, then set the compression.method option to gzip, e.g.
dim h 
set h = CreateObject("PocketSOAP.HTTPTransport")
h.option("compression.method") = "gzip"
' continue to use transport as usual ...

New Features for PocketSOAP 1.4

HTTP Compression

All HTTP requests now include a header in the request that indicates that we can handle a compressed response. If the response is compressed, the transport will automatically uncompress it. By default the request SOAP message is not compressed. To send compressed requests, call the new option method on the HTTP transport object, setting the compression.enabled property to true, e.g.
dim h 
set h = CreateObject("PocketSOAP.HTTPTransport")
h.option("compression.enabled") = true
' continue to use transport as usual ...

PocketPC HTTP Timeouts

HTTP Timeouts are now handled on the PocketPC, set the timeout property on the transport, the same way as you do on the Win32 version.
dim h 
set h = CreateObject("PocketSOAP.HTTPTransport")
' set timeout to 5 seconds (it defaults to 15 seconds)
h.timeout = 5000 

New Features for PocketSOAP 1.3

Attachments Support

You can now send and receive binary attachments to the SOAP message via either DIME or SwA. See the samples for details.
Support for document/literal style services has been improved, the serialization interfaces now allow access to typed attributes, e.g.
Private Sub ISoapSerializer_Serialize(  theVal As Variant, _
                                        ByVal ctx As PocketSOAP.ISerializerContext, _
                                        ByVal dest As PocketSOAP.ISerializerOutput)
    Dim val As Person
    Set val = theVal
    Dim d2 As ISerializerOutput2
    Set d2 = dest
    ' val.name and val.male will get serialized with a serializer based on their type.
    d2.SerializeAttribute val.name, "Name", ""
    d2.SerializeAttribute val.Male, "Male", ""
    dest.SerializeValue val.Age, "Age", "http://soapinterop.org/xsd"
    dest.SerializeValue val.id, "ID", "http://soapinterop.org/xsd"
End Sub

Private Sub ISoapDeSerializer_Start(    ByVal node As PocketSOAP.ISOAPNode, _
                                        ByVal ElementName As String, _
                                        ByVal Attributes As PocketSOAP.ISoapDeSerializerAttributes, _
                                        ByVal ns As PocketSOAP.ISOAPNamespaces)
    Set m_obj = CreateObject(m_comtype)
    node.Value = m_obj
    Set m_refs = New Collection
    Dim a As ISoapDeSerializerAttributes2
    Set a = Attributes
    m_obj.name = a.ValueAs("Name", "", "string", "http://www.w3.org/2001/XMLSchema")
    m_obj.Male = a.ValueAs("Male", "", "boolean", "http://www.w3.org/2001/XMLSchema")
End Sub

New Features for PocketSOAP 1.2

Enhanced EncodingStyle support

In addition to the current EncodingStyle property on the envelope, each node object can now adjust the encodingStyle. This is particularly useful for headers, which are typically defined using schemas rather then section 5 encoding. The serializer engine will disable the multi-ref features of section 5 if the encodingStyle is set to something other than the section 5 encoding URI. Nodes created via Nodes.Create will automatically inherit their encodingStyle from their parent, stand-alone nodes created through new (or CoCreateInstance) default to section 5 encoding. e.g.
dim e
set e = CreateObject("pocketSOAP.Envelope.2")
e.SetMethod "echoString", "http://soapinterop.org/"
e.Parameters.Create "inputString", "hello World"

set n = e.Headers.Create ("messageHeader",empty,"http://foo.org/")
n.encodingStyle= ""
n.mustUnderstand = true
n.Nodes.Create "msgID", 12345
wscript.echo e.serialize
this generates the following SOAP message
<S:Envelope
        S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'
        xmlns:a='http://foo.org/'
        xmlns:E='http://schemas.xmlsoap.org/soap/encoding/'
        xmlns:S='http://schemas.xmlsoap.org/soap/envelope/'
        xmlns:d='http://soapinterop.org/'
        xmlns:c='http://www.w3.org/2001/XMLSchema'
        xmlns:b='http://www.w3.org/2001/XMLSchema-instance'>
<S:Header>
<a:messageHeader S:mustUnderstand='1' S:encodingStyle=''><msgID b:type='c:short'>12345</msgID>
</a:messageHeader>
</S:Header>
<S:Body><d:echoString><inputString b:type='c:string'>hello World</inputString>
</d:echoString>
</S:Body></S:Envelope>

The RawTCP Transport

This is a simple TCP based transport that works with the TcpServer module in SOAP::Lite. This is useful when the service provider doesn't want to deploy a full blown HTTP based system. e.g.
set e = CreateObject("pocketSOAP.Envelope.2")
e.setMethod "test", "http://www.soaplite.com/ClearingHouse"
set t = CreateObject("pocketSOAP.RawTCPTransport")
t.send "rawtcp://some.server.org:8002", e.serialize
e.parse t
wscript.echo e.parameters.item(0).value

Local Type mappings support

One of the problems with the existing type mapping support, is that you can't cope with elements having the same name, but different types in different parts of the message. The local types support, allows you to register element name to type mappings as before, but also to specify that the mapping is only valid within the scope of a particular type. This allows you to have multiple elements <item> in a message, but for its type to be dependent upon the containing elements type. e.g.
const XSD = "http://www.w3.org/2001/XMLSchema"

set e = CreateObject("pocketSOAP.Envelope.2")
e.SerializerFactory.ElementMapping "c","","three","http://soapinterop.org/" 
e.SerializerFactory.LocalTypeMapping "one","http://soapinterop.org/","item","","string",XSD
e.SerializerFactory.LocalTypeMapping "two","http://soapinterop.org/","item","","int", XSD
e.SerializerFactory.LocalTypeMapping "three","http://soapinterop.org/","item","","float",XSD

e.parse GetTestMsg

for i = 0 to e.parameters.count-1
	set n = e.parameters.item(i).Nodes.item(0)
	wscript.echo n.Name & " -> " & n.Value & " -> " & TypeName(n.Value)
next

Function GetTestMsg()
	m = "<S:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' " + _
		 "SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' " + _
		 "xmlns:E='http://schemas.xmlsoap.org/soap/encoding/' " + _
		 "xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' " + _
		 "xmlns:d='http://soapinterop.org/' " + _
		 "xmlns:xs='http://www.w3.org/2001/XMLSchema' " + _
		 "xmlns:xi='http://www.w3.org/2001/XMLSchema-instance'>" + _
		 "<S:Body><d:testFooResponse>" + _
		 "<a xi:type='d:one'><item>String</item></a>" + _
		 "<b xi:type='d:two'><item>1414</item></b>" + _
		 "<c><item>33.33</item></c>" + _ 
		 "</d:testFooResponse></S:Body></S:Envelope>"
	GetTestMsg = m
end Function
This generates the following output.
item -> String -> String
item -> 1414 -> Long
item -> 33.33 -> Single

New Features for PocketSOAP 1.1

The Nodes Object

The Parameters property returns a Nodes object, which allows you to read/write/create new nodes in the parameters tree. Each node object also contains a nodes property, which make it much easer to construct complex types, e.g.
dim e, a
set e = CreateObject("pocketSOAP.Envelope.2")
e.methodName = "addAddress"
e.URI = "http://tempuri.org/"
e.Parameters.Create "name", "Simon Fell"
set a = e.Parameters.Create "address",""
a.Nodes.Create "street", "100 Spear Street"
a.Nodes.Create "city", "San Francisco"
a.Nodes.Create "state', "CA"
a.nodes.Create "zip", "94107"
this generates the following SOAP message
<S:Envelope
        S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'
        xmlns:S='http://schemas.xmlsoap.org/soap/envelope/'
        xmlns:E='http://schemas.xmlsoap.org/soap/encoding/'
        xmlns:a='http://tempuri.org/'
        xmlns:b='http://www.w3.org/2001/XMLSchema-instance'
        xmlns:c='http://www.w3.org/2001/XMLSchema'>
<S:Body><a:addAddress><name b:type='c:string'>Simon Fell</name>
<address href='#a'/>
</a:addAddress>
<address E:root='0' id='a'><street b:type='c:string'>100 Spear Street</street>
<city b:type='c:string'>San Francisco</city>
<state b:type='c:string'>CA</state>
<zip b:type='c:string'>94107</zip>
</address>
</S:Body></S:Envelope>

Headers

The Headers property allows access to the headers of the SOAP message. This uses the node/nodes objects the same as the parameters property does. e.g.
dim e, h
set e = CreateObject("pocketSOAP.Envelope.2")
e.methodName = "placeOrder"
e.URI = "http://tempuri.org/"
set h = e.headers.Create ("Transaction", "42", "http://soap.tip.org/")
h.MustUnderstand = true
e.Parameters.Create "item", "widget 19"
e.Parameters.Create "number", 5
wscript.echo e.serialize
This generates the following SOAP message
<S:Envelope
        S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'
        xmlns:S='http://schemas.xmlsoap.org/soap/envelope/'
        xmlns:E='http://schemas.xmlsoap.org/soap/encoding/'
        xmlns:a='http://soap.tip.org/'
        xmlns:b='http://www.w3.org/2001/XMLSchema-instance'
        xmlns:c='http://www.w3.org/2001/XMLSchema'
        xmlns:d='http://tempuri.org/'>
<S:Header>
<a:Transaction S:mustUnderstand='1' b:type='c:string'>42</a:Transaction>
</S:Header>
<S:Body><d:placeOrder><item b:type='c:string'>widget 19</item>
<number b:type='c:int'>5</number>
</d:placeOrder>
</S:Body></S:Envelope>

Multi-Dim arrays

The standard array serializer supports all the various array options, single dimension, multi-dimension, partial & sparse arrays. e.g.
dim e, a(1,1)
a(0,0) = "one"
a(0,1) = "two"
a(1,0) = "three"
a(1,1) = "four"
set e = CreateObject("pocketSOAP.Envelope.2")
e.methodName = "strings"
e.URI = "http://tempuri.org/"
e.Parameters.Create "strArray", a
wscript.echo e.serialize
This generates the folloiwng SOAP message
<S:Envelope
        S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'
        xmlns:S='http://schemas.xmlsoap.org/soap/envelope/'
        xmlns:E='http://schemas.xmlsoap.org/soap/encoding/'
        xmlns:a='http://tempuri.org/'
        xmlns:b='http://www.w3.org/2001/XMLSchema'
        xmlns:c='http://www.w3.org/2001/XMLSchema-instance'>
<S:Body><a:strings><strArray E:arrayType='b:anyType[2,2]'><i c:type='b:string'>one</i>
<i c:type='b:string'>two</i>
<i c:type='b:string'>three</i>
<i c:type='b:string'>four</i>
</strArray>
</a:strings>
</S:Body></S:Envelope>

base64 support

There's a base64 serializer for serializing byte arrays.
Dim e, a(5) As Byte
a(0) = 10: a(1) = 20: a(3) = 30: a(4) = 40: a(5) = 50
Set e = CreateObject("pocketSOAP.Envelope.2")
e.methodName = "echoBase64"
e.URI = "http://soapinterop.org/"
e.Parameters.Create "inputBase64", a
MsgBox e.serialize
<S:Envelope
	S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'
	xmlns:S='http://schemas.xmlsoap.org/soap/envelope/'
	xmlns:E='http://schemas.xmlsoap.org/soap/encoding/'
	xmlns:a='http://soapinterop.org/'
	xmlns:b='http://www.w3.org/2001/XMLSchema-instance'>
<S:Body><a:echoBase64><inputBase64 b:type='E:base64'>ChQAHigy</inputBase64>
</a:echoBase64>
</S:Body></S:Envelope>

SetMethod

The envelope object has an addition method SetMethod that can be used to set the methodName & URI in one go, e.g.
dim e
set e= CreateObject("pocketSOAP.Envelope.2")
e.SetMethod "add", "http://simon.fell.com/calc"

Multi-Refs / Object Graph Serialization

There's full support for serializing & deserializing object graphs, including circular references etc. Here's an example of a serialized ring buffer
dim soap
set soap = CreateObject("PocketSOAP.Envelope")
soap.SetMethod "Add", "http://simon.fell.com/calc"
dim n, last
set h = CreateNode ( "f", a, nothing ) 
set last = h
for i = 1 to 5
	set n = CreateNode ( "a", i, last )
	set last = n 
next
	
' make it a ring buffer
h.Nodes.ItemByName("next").value = last
soap.Parameters.Create "head", n
wscript.echo soap.serialize

Function CreateNode ( name, v, nextNode )
	dim n
	set n = CreateObject("pocketSOAP.Node")
	n.name = name 
	n.type = "linkedlist"
	n.typeNS = "http://soapinterop.org"

	n.Nodes.Create "value", v
	n.Nodes.Create "next", nextNode

	Set CreateNode = n	
end Function
<S:Envelope
        S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'
        xmlns:S='http://schemas.xmlsoap.org/soap/envelope/'
        xmlns:E='http://schemas.xmlsoap.org/soap/encoding/'
        xmlns:a='http://simon.fell.com/calc'
        xmlns:b='http://soapinterop.org'
        xmlns:c='http://www.w3.org/2001/XMLSchema-instance'
        xmlns:d='http://www.w3.org/2001/XMLSchema'>
<S:Body><a:Add><head href='#a'/>
</a:Add>
<b:linkedlist E:root='0' id='f'><value></value>
<next href='#a'/>
</b:linkedlist>
<b:linkedlist E:root='0' id='e'><value c:type='d:int'>1</value>
<next href='#f'/>
</b:linkedlist>
<b:linkedlist E:root='0' id='d'><value c:type='d:int'>2</value>
<next href='#e'/>
</b:linkedlist>
<b:linkedlist E:root='0' id='c'><value c:type='d:int'>3</value>
<next href='#d'/>
</b:linkedlist>
<b:linkedlist E:root='0' id='b'><value c:type='d:int'>4</value>
<next href='#c'/>
</b:linkedlist>
<b:linkedlist E:root='0' id='a'><value c:type='d:int'>5</value>
<next href='#b'/>
</b:linkedlist>
</S:Body></S:Envelope>

The PropertyBag serializer

pocketSOAP comes with a PropertyBag serializer, this will deserialize any COM object that implements IPersistPropertyBag to/from a SOAP complex type. In VB if you've set the Persistable property of a class to 1 - Persistable then VB will implement IPersistPropertyBag for you, making it easy to add SOAP support to your existing COM objects.

Serializer Factory

The Serializer Factory object controls the mapping between COM date types and SOAP date types. The SerializerFactory property on the Envelope object can be used to access the serializerFactory object. Once you got the SerializerFactory object, you can register new serializers or de-serializers and add additional mappings from element names to types. e.g.
Dim e As CoEnvelope
Set e = New CoEnvelope
Dim sf As ISerializerFactoryConfig
Set sf = e.SerializerFactory
sf.ElementMapping "phone", "", "phone", "http://apache.org/"
sf.ElementMapping "address", "", "address", "http://apache.org/"
sf.Deserializer "phone", "http://apache.org/", False, "ps.telephone", "pocketSOAP.SerializerPB.1"
sf.Deserializer "address", "http://apache.org/", False, "ps.address", "pocketSOAP.SerializerPB.1"
This adds two new element name mappings (these tell the de-serializer what type elements are that don't contain type information on the wire). In the example is says, any element called phone is of type {http://apache.org/}phone and any element called address is of type {http://apache.org/}address. It then registers two de-serializer mappings, one that maps the SOAP data type {http://apache.org/}phone to the com object ps.telephone and registers the de-serializer object pocketSOAP.SerializerPB.1 as the de-serializer that will map the data from the SOAP message to the COM object. It then does the same for address to ps.address using the same de-serializer.

Serializer Factory (more!)

The Serializer Factory contains support for both the 1999 XML Schema namespace and the 2001 XML Schema namespace. By default pocketSOAP will use the 2001 Schema namespace, however if you are calling a service that requires the use of the 1999 namespace, then you can set the PrimarySchema property to the value of the 1999 Schema namespace, and pocketSOAP will serialize using that format instead (including taking care of such differnces as ur-type vs anyType, timeInstant vs dateTime etc), e.g.
dim e, a
set e = CreateObject("pocketSOAP.Envelope.2")
e.methodName = "addAddress"
e.URI = "http://tempuri.org/"
e.Parameters.Create "name", "Simon Fell"
set a = e.Parameters.Create ("address","")
a.Nodes.Create "street", "100 Spear Street"
a.Nodes.Create "city", "San Francisco"
a.Nodes.Create "state", "CA"
a.nodes.Create "zip", "94107"
e.SerializerFactory.PrimarySchema = "http://www.w3.org/1999/XMLSchema"
wscript.echo e.serialize
this generates the following SOAP message
<S:Envelope
        S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'
        xmlns:S='http://schemas.xmlsoap.org/soap/envelope/'
        xmlns:E='http://schemas.xmlsoap.org/soap/encoding/'
        xmlns:a='http://tempuri.org/'
        xmlns:b='http://www.w3.org/1999/XMLSchema-instance'
        xmlns:c='http://www.w3.org/1999/XMLSchema'>
<S:Body><a:addAddress><name b:type='c:string'>Simon Fell</name>
<address href='#a'/>
</a:addAddress>
<address E:root='0' id='a'><street b:type='c:string'>100 Spear Street</street>
<city b:type='c:string'>San Francisco</city>
<state b:type='c:string'>CA</state>
<zip b:type='c:string'>94107</zip>
</address>
</S:Body></S:Envelope>

Write your own serializers

Need to [de]serializer your own custom types to/from SOAP ?, then you can write your own serializer and deserializer objects and pocketSOAP will call them at the relevant point during the [de]serialization process. Don't like one of the standard serializers, just write your own version all the serializers are pluggable. Want to de-serializer SOAP arrays into COM collections, no problem just write a new deserializer and off you go. Details on writing custom serializers and deserializers is including in the documentation.