ColdFusion and ASP.NET Web Service Interoperability (or Lack Thereof), Part II
Yesterday I was talking about some of the problems I had getting a service provider's ASP.NET client to work with my company's ColdFusion web service. Once we had that issue resolved the next step was to get our CFMX 6.1 application working with their ASP.NET web services.
Here is a sample SOAP 1.1 request and response for one of their web service methods. (This is from the ASP.NET auto generated documentation):
POST /service.asmx HTTP/1.1
Host: their.service.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/Company_Add"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Company_Add xmlns="http://tempuri.org/">
<txtCompanyName>string</txtCompanyName>
<txtCompanyAddress1>string</txtCompanyAddress1>
<txtCompanyAddress2>string</txtCompanyAddress2>
<txtCompanyZip>string</txtCompanyZip>
<txtCompanyFax>string</txtCompanyFax>
</Company_Add>
</soap:Body>
</soap:Envelope>
----------------
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Company_AddResponse xmlns="http://tempuri.org/">
<Company_AddResult>int</Company_AddResult>
<txtErrorMessage>string</txtErrorMessage>
</Company_AddResponse>
</soap:Body>
</soap:Envelope>
I originally tried to call this service using <cfinvoke> however I kept getting the following error:
I got this error no matter how I tried passing in the parameters so what I ended up doing is taking the brute force approach. I created a cfc which just wrapped <cfhttp>calls to the webservice. Below is an example of what I did.
<cfcomponent>
<cffunction access="public" name="int" output="false" returntype="mywebservice">
<cfargument name="URL" type="string" required="true">
<cfset instance = StructNew() />
<cfset instance.URL = arguments.URL />
<cfreturn this />
</cffunction>
<cffunction access="public" name="companyAdd" output="false" returntype="struct">
<cfargument name="companyName" type="string" required="true" />
<cfargument name="companyAddress1" type="string" required="false" default="" />
<cfargument name="companyAddress2" type="string" required="false" default="" />
<cfargument name="companyZip" type="string" required="false" default="" />
<cfargument name="companyFax" type="string" required="false" default="" />
<cfset var requestXML = "" />
<cfsavecontent variable="requestXML">
<Company_Add xmlns="http://tempuri.org/">
<txtCompanyName>#arguments.companyName#</txtCompanyName>
<txtCompanyAddress1>#arguments.companyAddress1#</txtCompanyAddress1>
<txtCompanyAddress2>#arguments.companyAddress2#</txtCompanyAddress2>
<txtCompanyZip>#arguments.companyZip#</txtCompanyZip>
<txtCompanyFax>#arguments.companyFax#</txtCompanyFax>
</Company_Add>
</cfsavecontent>
<cfreturn makeRequest("Company_Add",requestXML) />
</cffunction>
<cffunction access="private" name="makeRequest" output="false" returntype="struct">
<cfargument name="requestType" type="string" required="true" />
<cfargument name="requestXML" type="string" required="true" />
<cfset var httpXML = "" />
<cfset var cfhttp = "" />
<cfset var resultXML = "" />
<cfset var resultStruct = StructNew() />
<cfsavecontent variable="httpXML">
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>#arguments.requestXML#</soap:Body>
</soap:Envelope>
</cfsavecontent>
<cfhttp method="post" url="#instance.URL#">
<cfhttpparam type="header" name="SOAPAction" value="http://tempuri.org/#arguments.requestType#">
<cfhttpparam type="XML" value="#httpXML#">
</cfhttp>
<cfset resultXML = XMLParse(cfhttp.FileContent) />
<cfset resultStruct.result = resultXML.Envelope.Body['#arguments.requestType#Response']['#arguments.requestType#Result']['XmlText'] />
<cfset resultStruct.errorMessage = resultXML.Envelope.Body['#arguments.requestType#Response']['txtErrorMessage']['XmlText'] />
<cfreturn resultStruct />
</cffunction>
</cfcomponent>
I'm definitely not a SOAP expert and I don't know a whole lot about ColdFusion's underlying Apache Axis web service engine, so if anyone has other suggestions on how to handle this, or any insight whatsoever as to what the issue is I'd be glad to hear it.
