Earlier this week I worked with John Bliss on an interesting problem he had. Let me describe his issue, and the solution he came up, and what I learned from it.

John was trying to consume a web service. The web service demanded that a particular SOAP header be sent:

<soap:Header> <ApiUserAuthHeader xmlns="namespace"> <UserName>xxxxx</UserName> <Password>xxxxx</Password> <UserAccessKey>xxxx</UserAccessKey> </ApiUserAuthHeader> </soap:Header>

He created the header like so:

<cfset ApiUserAuthHeader = StructNew()> <cfset ApiUserAuthHeader.UserAccessKey = "xxxxx"> <cfset ApiUserAuthHeader.Password = "xxxxx"> <cfset ApiUserAuthHeader.UserName = "xxxxx"> <cfset AddSOAPRequestHeader(MyWebservice, "namespace", "ApiUserAuthHeader", ApiUserAuthHeader)>

So far so good, right? I've never actually used addSOAPRequestHeader, but just looking at his code it made sense to me. The result however was off:

<soapenv:Header> <ns1:ApiUserAuthHeader xmlns:ns1="namespace"> <item xmlns:ns2="http://xml.apache.org/xml-soap"> <key xsi:type="xsd:string">PASSWORD</key> <value xsi:type="xsd:string">xxxxx</value> </item> <item> <key xsi:type="xsd:string">USERNAME</key> <value xsi:type="xsd:string">xxxxx</value> </item> <item> <key xsi:type="xsd:string">USERACCESSKEY</key> <value xsi:type="xsd:string">xxxxx</value> </item> </ns1:ApiUserAuthHeader> </soapenv:Header>

If you compare this to what the API requires, you can see they don't match. The first suggestion I had was to change how he worked with the structures. When you do:

<cfset s = {}> <cfset s.name = "Ray">

to create a structure, ColdFusion will uppercase the struct key (name), to give you: s.NAME = "Ray". I recommended he try bracket notation, essentially:

<cfset s = {}> <cfset s["name"] = "Ray">

This didn't help either (although the resultant header did have the right case for the keys). I hashed this a bit more in my head and then I had an idea. He created the XML data pretty much the way I always did - with structure functions. Of course, ColdFusion also has native XML functions to create XML nodes/data. I never use them because the structure functions are simpler (to me!) and just plain work. In this case though switching to 'proper' XML manipulation functions worked perfectly for him:

<cfset doc = XmlNew()> <cfset doc.ApiUserAuthHeader = XmlElemNew(ApiUserAuthHeader, "namespace", "ApiUserAuthHeader")> <cfset doc.ApiUserAuthHeader.UserName = XmlElemNew(ApiUserAuthHeader, "UserName")> <cfset doc.ApiUserAuthHeader.UserName.XmlText = "xxxxx"> <cfset doc.ApiUserAuthHeader.UserAccessKey = XmlElemNew(ApiUserAuthHeader, "UserAccessKey")> <cfset doc.ApiUserAuthHeader.UserAccessKey.XmlText = "xxxxx"> <cfset doc.ApiUserAuthHeader.Password = XmlElemNew(ApiUserAuthHeader, "Password")> <cfset doc.ApiUserAuthHeader.Password.XmlText = "xxxxx"> <cfset AddSOAPRequestHeader(MyWebservice, "namespace", "ApiUserAuthHeader", doc)>

So I guess I don't have much to add here, but I'd be curious if this type of problem has tripped up others?