tags:

views:

720

answers:

2

I'm having the problem described here:

http://groups.google.com/group/microsoft.public.xml.soap/browse_thread/thread/029ee5b5d4fa2440/0895d73c5c3720a1

I am consuming a Web Service using Office 2003 Web Services Toolkit. This generates classes for all the data returned by my web service: one of the classes has a property that is an array which may be empty.

When I call the web service, the Generic Type Mapper raises an error: "array dimensions do not match definition".

Does anyone know of a solution to this problem that allows me to keep using the generated classes (I know I could just consume the raw XML)?

A: 

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:

  • It detects and handles the case of an empty array.

  • Or if the array is non-empty it delegates to the standard GenericTypeMapper.

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.

Joe
A: 

Hi,

I would be really interessed in your custonized DLL Joe, as I can't manage to compile it myself :( But I'm asking myself why do we need an external DLL. Can't we add a new class or a new module to our VBA project?

Or maybe you already found an easier solution?

Thanks for your help !

Ju

I'd be happy to let you have it for what it's worth if you give me contact info. But it's very simple - create a VB6 ActiveX DLL project with a single public class, and copy in the above code. Add references to MSSOAP30.dll and MSXML5.DLL or later. I found these DLLs by browsing to %CommonProgramFiles%\Microsoft Shared\OFFICE11. With these references the code should compile
Joe