问题描述: 在用非.NET客户端调用WebService中,按照使用Soap Toolkit中的指导实现起来很简单,但在实际使用过程中却发现一个问题。 假如Webservice提供的方法是:int SimpleMath.Add(int n1,int n2),返回值是n1+n2,但按照soap toolkit提供的例子,使用VC进行调用,得到的返回值却是0。 记录下我的解决过程,备忘。 试验环境: OS:WindowsXP Professional WebService:VS.NET 2003 WebService运行环境:IIS 客户端:VC6.0,VS.NET中的VC SoapToolkit SDK:3.0 问题再现: 看Toolkit中稍微修改一下之后的例子代码: #include <stdio.h> #import "msxml4.dll" using namespace MSXML2; #import "C:/Program Files/Common Files/MSSoap/Binaries/mssoap30.dll" / exclude("IStream","IErrorInfo","ISequentialStream","_LARGE_INTEGER",/ "_ULARGE_INTEGER","tagSTATSTG","_FILETIME") using namespace MSSOAPLib30; int test2() { ISoapSerializerPtr Serializer; ISoapReaderPtr Reader; ISoapConnectorPtr Connector; // Connect to the service Connector.CreateInstance(__uuidof(HttpConnector)); Connector->Property["EndPointURL"] = "http://localhost/WSTest/SimpleMath.asmx?WSDL"; Connector->Connect(); // Begin message Connector->Property["SoapAction"] = "http://tempuri.org/Add"; Connector->BeginMessage(); // Create the SoapSerializer Serializer.CreateInstance(__uuidof(SoapSerializer)); // Connect the serializer to the input stream of the connector Serializer->Init(_variant_t((IUnknown*)Connector->InputStream)); // Build the SOAP Message Serializer->startEnvelope("","",""); Serializer->startBody(""); Serializer->startElement("Add","http://tempuri.org/",""); Serializer->startElement("n1",""); Serializer->writeString("5"); Serializer->endElement(); Serializer->startElement("n2",""); Serializer->writeString("10"); Serializer->endElement(); Serializer->endElement(); Serializer->endBody(); Serializer->endEnvelope(); // Send the message to the web service Connector->EndMessage(); // Let us read the response Reader.CreateInstance(__uuidof(SoapReader)); // Connect the reader to the output stream of the connector Reader->Load(_variant_t((IUnknown*)Connector->OutputStream),""); // Display the result printf("Answer: %s/n",(const char*)Reader->RPCResult->text); return 0; } 返回结果应该是15,但实际却返回了0。 在网上搜索发现有人提议把WebService的方法的参数改为string,然后在方法内部转换,我觉得这不是一个好办法。事实上,我经过发现,这样的实现问题会更多。 返回结果应该是15,但实际却返回了0。 在网上搜索发现有人提议把WebService的方法的参数改为string,然后在方法内部转换,我觉得这不是一个好办法。事实上,我经过发现,这样的实现问题会更多。 分析过程: 用soap toolkit的跟踪工具MSSoapT看一下,客户端到底向WebService发送了什么数据: <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body SOAP-ENV:encodingStyle=""> <SOAPSDK1:Add xmlns:SOAPSDK1="http://tempuri.org/" SOAP-ENV:encodingStyle=""> <n1 SOAP-ENV:encodingStyle="">5</n1> <n2 SOAP-ENV:encodingStyle="">10</n2> </SOAPSDK1:Add> </SOAP-ENV:Body> </SOAP-ENV:Envelope> 再看看vs.NET调试中,IE浏览器发出的数据(模板): <?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> <Add xmlns="http://tempuri.org/"> <n1>int</n1> <n2>int</n2> </Add> </soap:Body> </soap:Envelope> 区别在哪里?soaptoolkit的数据中,多了个encodingStyle属性,尽管没有制定值。我们想办法屏蔽这个属性。 在SoapSerializer30的startElement方法中的参数中按照如下方式调用,可以不制定这个属性。 改代码如下: ... Serializer->startElement("Add","NONE",""); Serializer->writeString("10"); Serializer->endElement(); Serializer->endElement(); ... 但返回结果还是0,看来和encodingStyle无关。看看跟踪情况: <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body SOAP-ENV:encodingStyle=""> <SOAPSDK1:Add xmlns:SOAPSDK1="http://tempuri.org/"> <n1>5</n1> <n2>10</n2> </SOAPSDK1:Add> </SOAP-ENV:Body> </SOAP-ENV:Envelope> 问题解决: 比较一下vs.net中发出的请求,差别在哪里?认真看一下,n1和n2没有指定命名空间,那么就指定一下吧。 把代码改成: Serializer->startElement("Add",""); Serializer->writeString("10"); Serializer->endElement(); Serializer->endElement(); 测试结果正常了,返回15。 看看这时候发出的xml数据: <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body SOAP-ENV:encodingStyle=""> <SOAPSDK1:Add xmlns:SOAPSDK1="http://tempuri.org/"> <SOAPSDK1:n1>5</SOAPSDK1:n1> <SOAPSDK1:n2>10</SOAPSDK1:n2> </SOAPSDK1:Add> </SOAP-ENV:Body> </SOAP-ENV:Envelope> 原因: 我也无法总结到底是谁的问题:( 也许是VS.NET的问题,也许是SoapToolKit的问题,也许是他提供的例子自身就有问题,也许是我的运行环境有问题,当然,更也许是我还没有真正理解xml的命名空间或没有正确使用WebService。