ColdFusion Muse

Passing an Array to a .NET Webservice

Here's a problem that will leave you scratching your head should you ever run into it. Consider a simple .NET web service that requires an "array of strings". The goal was to make use of a web service API published by Smarter Mail. I wanted a programmatic way of adding email aliases - groups of emails that function under a single address. The web service methods provided by the smarter mail API could not be simpler. Each request requires a username, password, domain and then additional stuff to make it work. For example, the "GetAlias()" function allowed me to pass in a domain and alias and get a list of emails already associated with that alias.

The problem came when it was time to add or update an alias. The argument for "addresses" to pass to the .NET service looked like "an array of strings" (that's how the help docs referred to is as well). The node in the XML looked pretty simple:

<AddAlias xmlns="http://tempuri.org/">
<AuthUserName>string</AuthUserName>
<AuthPassword>string</AuthPassword>
<DomainName>string</DomainName>
<AliasName>string</AliasName>
<Addresses>
<string>string</string>
<string>string</string>
</Addresses>
</AddAlias>

Now I can think of several ways to create an array of strings in ColdFusion so I started giving it the old college try. Unfortunately each attempt ended in failure. I could not figure out how to get a data type instantiated in CF to match the data type that .NET expected. I ended up experimenting with several different approaches to the array syntax.

After trying the straight up CF array syntax (as in x = arrayNew(1)), I tried JavaCasting to an array (seems obvious right?).

<Cfscript>
    Addresses = Javacast("string[]", ArrayOfAddresses);
</cfscript>

That didn't work so I tried directly instantiating a Java "arrayList" (as in createobject("java","java.util.ArrayList")), but that also yielded no results. I tried the "toArray()" member of the array class (based on this excellent post from Christian Cantrell on Passing ColdFusion Arrays to Java) but that was also a bust. I tried different ways of initing an array (like the bracket syntax). No matter what I tried I got the dreaded "argument type mismatch" error. Finally I stumbled onto this post on the Smarter Tools forum. A user with the same problem that I had created this function:

<cfscript>
    function SmartArray(lItems,delim){
var ArrayContainer=StructNew();
ArrayContainer.string=ListToArray(lItems,delim);
return ArrayContainer;
}
</cfscript>

What gives? His little function definitely solved my problem - but why? Looking carefully at the XML you can see why. The code is not calling for an array of string. It is calling for a member named "string" containing an array. If "addresses" was supposed to be an array of strings the node would look something like:

<Addresses>string</Addresses>
<Addresses>string</Addresses>
<Addresses>string</Addresses>
As it is written the array in question belongs not to "addresses" but to "addresses.string". My problem was getting hung up on the word "string" that was being used to label the node. I simply took it to be a type without recognizing it as an actual member of "addresses". All I needed was a wrapper "string" containing an array. Once I used this function I was able to work out the details of my Smarter Mail Web service and add a list of email addresses to an alias using code like this:

<cfscript>
    addresses = smartArray("email1@example.com,email2@example.com",",");
    mailServer.addAlias(AuthUsername=au, AuthPassword=pw, DomainName=domain, AliasName=aliasName, addresses=addresses);
</cfscript>

To summarize, if your .NET service calls for an array of something, look carefully at the syntax and figure out the nature of the way the data is organized. Analyzing the XML carefully will give you a head start and keep you from puzzling till your puzzler is sore.

Comments
Dominic Latham's Gravatar Great tip. Thanks.
# Posted By Dominic Latham | 4/29/09 9:43 AM
David Hazell's Gravatar That's a really interesting article, and I thought it might help me out with a little problem I am facing, but alas it doesn't appear to. Now I am probably being a complete simpleton, but I can't get a web service call to work because I am getting a "java.lang.IllegalArgumentException: argument type mismatch" error... I'm pretty sure it's down to the ArrayOfInt I am supposed to be passing in going in wrong - here's an excerpt from the WSDL:

<s:element minOccurs="0" maxOccurs="1" name="UserIDAllowSendToList" type="tns:ArrayOfInt"/>
</s:sequence>
</s:complexType>
</s:element>
?
<s:complexType name="ArrayOfInt">
?
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="int" type="s:int"/>
</s:sequence>
</s:complexType>

How do I pass something into the web service that will work in CF7?

Any help would be greatly appreciated!

Thanks

David
# Posted By David Hazell | 4/30/09 11:49 AM
David Hazell's Gravatar After a lot more looking around, I found this:

http://phillhowson.com/blog/index.cfm/2006/9/1/Col...

Which gave me the answer I was looking for.

Happy Days...

David

:-)
# Posted By David Hazell | 5/1/09 5:25 AM
Joel's Gravatar Thanks Mark--this post was a lifesaver!
# Posted By Joel | 9/12/09 3:25 AM
Aaron Neff's Gravatar Yes, thank you Mark.. and Joel. :) +1 on the lifesaver!
# Posted By Aaron Neff | 9/12/09 6:34 AM
Ben's Gravatar Thanks very much for that stopped me banging my head on a desk wondering why I couldn't get that working.
# Posted By Ben | 10/25/10 7:45 AM



Blog provided and hosted by CF Webtools. Blog Sofware by Ray Camden.