Since there are no takers, I'll describe what I've done to date in case anyone else has a similar issue.
On my client (using Office 2003 Web Services Toolkit) I want to receive a collection of objects which have a property that itself is a collection of objects. For example, a collection of Customer objects from a C# web service where the Customer class looks something like:
public class Customer
{
public string Name { get; set; }
public Collection<Address> Addresses { get; }
}
The problem I have is that the Addresses property can sometimes be an empty collection, and the SOAP30 GenericTypeMapper is not able to handle this.
In my specific case, the client did not actually need the collection of addresses, I just want to be able to get the other properties of the Customer class. So I don't really care what's in the "Addresses" variant property that's created by the Web Services Toolkit.
What I've done is create a VB6 ActiveX DLL with a class with a minimalist implementation of ISoapMapper that always returns an uninitialized object reference:
Implements ISoapTypeMapper
Private Function ISoapTypeMapper_Iid() As String
End Function
Private Sub ISoapTypeMapper_Init(ByVal par_Factory As MSOSOAPLib30.ISoapTypeMapperFactory, ByVal par_Schema As MSXML2.IXMLDOMNode, ByVal par_WSMLNode As MSXML2.IXMLDOMNode, ByVal par_xsdType As MSOSOAPLib30.enXSDType)
End Sub
Private Function ISoapTypeMapper_Read(ByVal par_soapreader As MSOSOAPLib30.ISoapReader, ByVal par_Node As MSXML2.IXMLDOMNode, ByVal par_encoding As String, ByVal par_encodingMode As MSOSOAPLib30.enEncodingStyle, ByVal par_flags As Long) As Variant
Set ISoapTypeMapper_Read = Nothing
End Function
Private Function ISoapTypeMapper_SchemaNode() As MSXML2.IXMLDOMNode
Set ISoapTypeMapper_SchemaNode = Nothing
End Function
Private Function ISoapTypeMapper_VarType() As Long
ISoapTypeMapper_VarType = vbObject
End Function
Private Sub ISoapTypeMapper_Write(ByVal par_ISoapSerializer As MSOSOAPLib30.ISoapSerializer, ByVal par_encoding As String, ByVal par_encodingMode As MSOSOAPLib30.enEncodingStyle, ByVal par_flags As Long, par_var As Variant)
End Sub
Private Function ISoapTypeMapper_XsdType() As MSOSOAPLib30.enXSDType
ISoapTypeMapper_XsdType = enXSDUndefined
End Function
Then I modified the WSML generated by the Web Services Toolkit to use this implementation for the appropriate property:
Dim str_WSML As String
str_WSML = "<servicemapping>"
str_WSML = str_WSML & "<service name='MyService'>"
str_WSML = str_WSML & "<using PROGID='MSOSOAP.GenericCustomTypeMapper30' cachable='0' ID='GCTM'/>"
str_WSML = str_WSML & "<using PROGID='SoapHelper.EmptyArrayMapper' cachable='0' ID='EATM'/>" ' <== Added this line
str_WSML = str_WSML & "<types>"
...
str_WSML = str_WSML & "<type name='ArrayOfAddress' targetNamespace='http://...' uses='EATM' targetClassName='struct_Address'/>" '<== Added this line
str_WSML = str_WSML & "<type name='Address' targetNamespace='http://groupama-am.fr/gfp/griot/services/data' uses='GCTM' targetClassName='struct_Address'/>"
...
This achieved what I needed for this application.
It seems to me that it may be possible to achieve support for empty arrays more generally by implementing ISoapMapper in such a way that:
I'd still be interested to hear if anyone has solved the general problem. Possibly not as the SOAP client is obsolete and no longer supported by Microsoft.