This is a long one - apologies....
Is there a reliable way of returning lists from C# to VBA via a web service?
I've got a web service that returns a 'result', which consists of some doubles, strings and so on (it's an engineering calculation). I also return a list of 'Errors' and 'Messages' which contain information on the calc and give you some idea of what, if anything, went wrong. So these lists are potentially empty.
Here's my C# 'NoteList' class, and both the 'Errors' and 'Messages' are of this type.
public class Note
{
public int ID;
public string Message;
public Note()
{
ID = 0;
Message = "";
}
public Note(int aID, string aMessage)
{
ID = aID;
Message = aMessage;
}
}
public class NoteList : List<Note>
{
}
All pretty straightforward.
My 'Result' class contains two lists, thus:
public class Result
{
// Lists
public NoteList ErrorList = new NoteList();
public NoteList MessageList = new NoteList();
// Lots of other stuff...
}
So far, so good...
I've used the VBA Web References Toolkit to construct some VBA proxy 'struct' to hold a result. The generated code looks like this...
A 'struct_note':
Public ID As Long
Public Message As String
A 'struct_Result':
'"ErrorList" is an array with elements defined as struct_Note
'See Complex Types: Arrays in Microsoft Office 2003 Web Services Toolkit Help
'for details on implementing arrays.
Public ErrorList As Variant
'"MessageList" is an array with elements defined as struct_Note
'See Complex Types: Arrays in Microsoft Office 2003 Web Services Toolkit Help
'for details on implementing arrays.
Public MessageList As Variant
' plus the other stuff....
I've included the comments in the above listing as generated by the Toolkit.
In my VBA I create my result and use it as follows:
Dim r as struct_Result
Dim ws As clsws_MyWebService ' This is another generated proxy class
and I populate it thus:
Set r = ws.wsm_SomeMethod()
do stuff and then 'nothing' it when I'm done
Set r = nothing
Right - to my problem...
I want to run this web method a gazillion times on an Excel sheet and note the errors and messages that come back. So I put the above in a loop
for i = 1 to 10000
Set r = ws.wsm_SomeMethod()
' do some analysis and write back to the spreadsheet
Set r = nothing
next i
This works fine UNTIL I get back a result which has no errors in it, ie the ErrorList is empty. I then get a VB error saying

(source: bigsmoke.com)
I suspect that VB is constructing something that requires an ErrorList with something in it and complains that the array is of zero size.
Anyone out there in stackoverflow land got any ideas as to how to solve this?
Thanks
sal
-------- [EDIT] BELOW ADDED FOLLOWING RESPONSE FROM nitzmahone -------------------
I've modified my code to permit a null list as follows
public class Result
{
// Lists
[XmlElement(IsNullable = true)]
public NoteList ErrorList = new NoteList();
[XmlElement(IsNullable = true)]
public NoteList MessageList = new NoteList();
// Lots of other stuff...
}
This modifies the WSDL in a way I wasn't expecting. Prior to adding the IsNullable attributes the WSDL generated for a 'Result' looked like:
<s:complexType name="Result">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="ErrorList" type="tns:ArrayOfNote" />
<s:element minOccurs="0" maxOccurs="1" name="MessageList" type="tns:ArrayOfNote"/>
// Stuff deleted for clarity...
</s:sequence>
</s:complexType>
<s:complexType name="ArrayOfNote">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="Note" nillable="true" type="tns:Note" />
</s:sequence>
We've got a 'Result' containing an 'ArrayOfNote' containing nullable 'Notes'.
After adding the [XmlElement(IsNullable = true)] to the Lists I get this WSDL:
<s:complexType name="Result">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="ErrorList" nillable="true" type="tns:Note" />
<s:element minOccurs="0" maxOccurs="unbounded" name="MessageList" nillable="true" type="tns:Note" />
// Stuff deleted for clarity...
</s:sequence>
</s:complexType>
I've lost the "ArrayOfNote" and I'm left with a single (ie non array) 'ErrorList' which is a 'Note'. I've run some sample cases and indeed with the addition of the [XmlElement(IsNullable = true)] to the Lists I get back (in the VB) a single value which is always the last element of the server side C# lists.
Should I be putting the [XmlElement(IsNullable = true)] somewhere else? Where??
Thanks!
Steve