|
Download source files - 3 Kb
Download demo project - 25 Kb

Introduction
SOAP has a lot of potential for providing interfaces for web services.
SOAP will be good for a lot of different types of services. The SOAP toolkit
from Microsoft provides developers with a good starting place for learning SOAP.
The SOAP Toolkit 2.0 Beta 1 was released on Jan 3, 2000. It provides new samples
and a help file to explain the new interfaces. The samples provide both client
and server examples to build from in developing your own services.
One thing that is a bit neglectd in the samples (provided by Microsoft) is the
use of C++ to develop the services. All of the samples are written to show the
use of VB and ASP. This is fine and dandy, but from the use of SOAP my work needs
to use C++. So I looked on the Internet for examples of SOAP using VC. To my
surprise, I only found one, and it used the SOAP Toolkit 1.0 instead of the latest 2.0.
Since the VB samples worked perfectly fine, I decided to develop a client application
using VC to talk to the VB Web Service. I started with the Low-Level VB Calculator
program and the VC sample that I had from the SOAP Toolkit 1.0.
To include the COM interfaces from the SOAP DLLs, the #import
directive was used. This was used for the MSSOAP1.dll and a using clause was added to use
the MSSOAPLib namespace. The VB sample used a WinInetConnector to connect to the webserver
for the service. This interface is not in the MSSOAPLib namespace. WiSC10.dll was also
imported so that I had the connector that was needed.
This second import led to problems. I had never had to import more than one DLL in any of my
previous projects. I was getting a fatal error LNK1179: invalid or corrupt file: duplicate comdat
"_IID_ISoapConnector" link error. After some research,
I found that I had to remove the named_guids from the second import line. This
solved my linking error and allowed the rest of the coding to go a lot smoother. An
exclude statement was included to remove some compiler warnings about automatic excludes.
#import "C:\\Program Files\\MSSoapSDK\\Binaries\\MSSOAP1.dll" named_guids raw_interfaces_only exclude("IStream","ISequentialStream","_LARGE_INTEGER","_ULARGE_INTEGER","tagSTATSTG","_FILETIME")
#import "C:\\Program Files\\MSSoapSDK\\Binaries\\WiSC10.dll" raw_interfaces_only exclude("IStream","ISequentialStream","_LARGE_INTEGER","_ULARGE_INTEGER","tagSTATSTG","_FILETIME")
using namespace MSSOAPLib;
From here, the rest of the conversion from the VB code to the C++ interfaces was simple. This
was fairly straight forward for anyone that has done conversions before. Smart pointers were
used to make the creating and releasing of objects simpler.
SOAP Client Summary
For this VC example, I decided to use the one VC sample that I had found online as a base for
development. The problem with this is that it was a console application and not a windowed
application. I decided to still develop it using the console based app and just stick with
one type of command to the server. Including this code into a normal Window application should
be a trivial thing for most VC COM developers.
To begin this low-level SOAP client, you need to create a SoapConnector. The implementation of
the SoapConnector could use any type of transport protocol such as HTTP, FTP, or SMTP. The
SOAP documentation says that there are three different SoapConnector implementations included
with the SOAP Toolkit 2.0. These implementations are WinInetConnector, XmlHttpConnector (default
for 9x/Me clients), and HttpLibConnector (default for NT/2K clients). I choose to use the
WinInetConnector since the VB sample that I was basing my code on used it. I went back to try the
other implemetations of the SoapConnector and all of them worked correctly on Win2k.
Connector = NULL;
Connector.CreateInstance(__uuidof(WinInetConnectorLib::WinInetConnector));
Connector->put_Property(endpoint,vEndPoint);
Connector->Connect(NULL);
Connector->put_Property(action,vAction);
Connector->BeginMessage(NULL);
After creating the SoapConnector, the EndPointURL was set and the Connect
method was called. This allows the code to connect to the web service. The SoapAction
was then set to uri:Multiply to tell the server what action I was going to be requesting.
This follows the VB example from the toolkit.
The next step is to create the SoapSerializer. The SoapSerializer is the interface that allows you to
create the XML message and send it to the server.
Serializer = NULL;
Serializer.CreateInstance(__uuidof(SoapSerializer));
Connector->get_InputStream(&inputstream);
_variant_t stream = inputstream;
Serializer->Init(stream);
Serializer->startEnvelope(NULL,NULL,NULL);
Serializer->startBody(NULL);
Serializer->startElement(method,command,NULL,m);
Serializer->startElement(a,NULL,NULL,NULL);
Serializer->writeString(val1);
Serializer->endElement();
Serializer->startElement(b,NULL,NULL,NULL);
Serializer->writeString(val2);
Serializer->endElement();
Serializer->endElement();
Serializer->endBody();
Serializer->endEnvelope();
Connector->EndMessage();
After the SoapSerializer is created, it needs to be attached to the input stream of the SoapConnector.
After this, the message is created and sent. As an interesting note, as you look over the source code,
the EndMessage method is the command that sends the message to the server.
Up to this point, we have built the XML command and sent it to the server to be executed. The next step
is to read the results. I left error checking off for this, but it can be added. To read the reply from
the server the client application needs to use a SoapReader. The SoapReader is connected to the output
stream of the SoapConnector. From there, the results can be read back in using an IXMLDOMElement object.
This is then displayed using std::cout.
Reader = NULL;
Reader.CreateInstance(__uuidof(SoapReader));
Connector->get_OutputStream(&outputstream);
_variant_t outstream = outputstream;
VARIANT_BOOL bres;
Reader->load(outstream,&bres);
MSSOAPLib::IXMLDOMElement *element;
Reader->get_RPCResult(&element);
BSTR buff;
element->get_baseName(&buff);
std::cout << W2A(buff) << std::endl;
element->get_text(&buff);
std::cout << W2A(buff) << std::endl;
Conclusion
Overall, SOAP communications is a simple thing for most developments. The low-level communications shown
here allows you to see the creation of the XML message as well as parse out the return message. This is a
simple example based on the ClcLVBCl sample that comes with the SOAP Toolkit 2.0 that shows the way that
SOAP can be used with VC.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 53 (Total in Forum: 53) (Refresh) | FirstPrevNext |
|
 |
|
|
Hi,
I am very new to SOAP. I am trying to develop an SOAP API to connect to CDRonDemand and get some info. Could anyone help me with some sample code or suggestions.
Thanks msurni
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
below shown my webservice developed .NET C# ... when i m using VC++ client... for method...
public double DoAdditon(double a, double b) { return (a + b); }
i m getting result 0 all the time where i m wrong ...plz tell me.. its urgent......
public class ClsService07 : System.Web.Services.WebService { public ClsService07() {
//Uncomment the following line if using designed components //InitializeComponent(); }
[WebMethod] public string HelloWorld() { return "Hello World in console "; }
[WebMethod] public double DoAdditon(double a, double b) { return (a + b); }
[WebMethod] public string DispalyMethod(string str) { return (str + "Inside DispalyMethod"); } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I don't see anything wrong with the code on the server side there. Can you call this web service from the test interface or from C#? What does your C++ look like?
Steve Maier
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
public double DoAdditon(double a, double b) { return (a + b); }
i m getting result 0 all the time where i m wrong ...plz tell me.. its urgent......
public class ClsService07 : System.Web.Services.WebService { public ClsService07() {
//Uncomment the following line if using designed components //InitializeComponent(); }
[WebMethod] public string HelloWorld() { return "Hello World in console "; }
[WebMethod] public double DoAdditon(double a, double b) { return (a + b); }
[WebMethod] public string DispalyMethod(string str) { return (str + "Inside DispalyMethod"); }
} ///////////////////////
this code workes fine...whith c# client but doesnt give me proper result in case of VC++ client ...where i m making mistake..? VC++ client using Toolkit 3.0
void DisplayAdd()
{ try { ISoapSerializerPtr Serializer; ISoapReaderPtr Reader; ISoapConnectorPtr Connector;
cout<<"test display:main\n";
// Connect to the service Connector.CreateInstance(__uuidof(HttpConnector30)); Connector->Property["EndPointURL"] ="http://localhost:2014/WebService07/Service.asmx"; Connector->Connect();
Connector-> Property["SoapAction"] = "http:/www.WbService07Name.com/webServices/DoAdditon";
// Begin message Connector->BeginMessage();
// Create the SoapSerializer Serializer.CreateInstance(__uuidof(SoapSerializer30));
// 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("DoAdditon",L"http://localhost:2014/WebService07/Service.asmx/","","");
//Serializer->startElement("Add","uri:Calc","","m"); Serializer->StartElement("a","","",""); Serializer->WriteString("5.9"); Serializer->EndElement();
Serializer->StartElement("b","","",""); Serializer->WriteString("10.8"); Serializer->EndElement();
Serializer->EndElement(); Serializer->EndBody(); Serializer->EndEnvelope();
// Send the message to the web service Connector->EndMessage();
// Let us read the response HRESULT hr = Reader.CreateInstance(__uuidof(SoapReader30));
// Connect the reader to the output stream of the connector Reader->Load(_variant_t((IUnknown*)Connector->OutputStream), "");
printf("Answer: %s\n",(const char*)Reader->RpcResult->text);
BSTR br; Reader->RpcResult->get_text(&br);
cout<<B2A(br)<<endl;
Connector=NULL; Serializer=NULL; Reader=NULL; } catch(...) { cout<<"Error in execution :main\n";
}
}
int _tmain(int argc, _TCHAR* argv[]) { CoInitialize(NULL);
DisplayAdd();
CoUninitialize();
return 0; }
result of addition showing 0 always...? how?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
A couple thing that I have noticed are that the code that is in the article is using NULL while you are using "" instead. I would also see about putting a breakpoint or some tracing in the web service. One more thing that you can try is a sniffing program like XMLSpy to see what is getting sent back and forth. Do this with a C# client and the C++ client and see the difference.
Steve Maier
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
but steave.... for same services C# client is giving exact reault .. but zero in case of Vc++ client. how come..this .is. is that i m missing something in some setting ... or..something..else since i m new to SOAP .. i would request you to guide me through... anyway i ve checked with you suggestion but..result are still zero.. infact whatever i m passing from client to server ...not reutrn to client as expecte.. i feel parameter are not passing coreectly to client...
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
still i m not getting....correct result where i m making mistake.. could you plz guid me step wise .. creating .NET C# web services and VC++ client . thanks
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Don't know if the OP figured this out, but [at least for me] using MSSOAP 3.0 you need to include the namespace URI for the serializer's StartElement calls; e.g., for a simple asmx .NET service (that by default uses tempuri.org) you would use:
hr = Connector.CreateInstance(__uuidof(HttpConnector30)); Connector->Property[_T("EndPointURL")] = _T("http://localhost/WSSandbox/MathSandboxWS.asmx");
hr = Connector->Connect();
Connector->Property[_T("SoapAction")] = _T("http://tempuri.org/DoAddition");
and then once the envelope and body are initialized,
hr = Serializer->StartElement(_T("DoAddition"), _T("http://tempuri.org/"),_T(""),_T(""));
hr = Serializer->StartElement(_T("a"), _T("http://tempuri.org/"),_T(""),_T("")); hr = Serializer->WriteString(_T("5.0")); hr = Serializer->EndElement();
hr = Serializer->StartElement(_T("b"), _T("http://tempuri.org/"),_T(""),_T("")); hr = Serializer->WriteString(_T("10.0")); hr = Serializer->EndElement();
I tried his code as posted (substituting tempuri.org as the NS URI) and got zero until I used a consistent NS URI; omitting the URI on either leaves the value as 0 so you get the other addend as the answer (e.g., leave the second arg of the StartElement call using a and the DoAddition call will return 10 as the answer).
HTH,
Steve
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi,
I have a similar C++ SOAP client.
I am facin a problem in which I am getting Authentication error while sending a message. With this error server is sending me "nonce" in the responce.
I want to use that "nonce" and send the message again..
Any way to catch the error ?
Thanks, Amit.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hello,
We are developing a C++ SOAP client program by using MSSOAPLib. Our development environment is Windows Xp Professional, Visual Studio .NET 2003. Our program works correctly in Xin Xp (local computer). But with Windows 2000, it fails in some computers and works correctly in some other.
Our code is below, the failure point in Win2000 computer is the part where we create the ISoapConnectorPtr object (int hr = Connector.CreateInstance(__uuidof(HttpConnector))
The CreateInstance method returns the following log:
////////// LOG //////////////////////////////////////////////////// 2005-08-14 08:48:17 - http://127.0.0.1/WebServiceBetek/Service.asmx 2005-08-14 08:48:17 - 2 2005-08-14 08:48:17 - CreateInstance Method 2005-08-14 08:48:17 - Function Return = -2147221164 2005-08-14 08:48:17 - 2.1.1 2005-08-14 08:48:17 - COM ERROR 2005-08-14 08:48:17 - 2005-08-14 08:48:17 - Invalid pointer 2005-08-14 08:48:17 - Error 2005-08-14 08:48:17 - Code = 80004003 2005-08-14 08:48:17 - Code meaning = Invalid pointer 2005-08-14 08:48:17 - Source = (null) ////////// LOG ////////////////////////////////////////////////////
So we have the invalid pointer problem (80004003). But there is no failure with WinXP computers and some other Win2000 computers. As I said above, all computers seem to have the same configuration : Microsof .NET Framework 1.1, MS SOAP Toolkit 3.0 and necessary service packs.
What can be the reason for this failure? Thanks in advance..
Levent
////////// CODE //////////////////////////////////////////////////// #import "msxml3.dll" using namespace MSXML2;
#import "C:\Program Files\Common Files\MSSoap\Binaries\MSSOAP1.dll" \ exclude("IStream", "ISequentialStream", "_LARGE_INTEGER", \ "_ULARGE_INTEGER", "tagSTATSTG", "_FILETIME") using namespace MSSOAPLib;
CString strRequest;
CoInitialize(NULL);
ISoapSerializerPtr Serializer = NULL; ISoapReaderPtr Reader = NULL; ISoapConnectorPtr Connector = NULL; CString strFsmsWebServiceUrl = "http://127.0.0.1/WebServiceBetek/Service.asmx";
printf("WEB SERVICE URL"); printf(strFsmsWebServiceUrl.GetBuffer()); printf("2"); // Connect to the service int hr = Connector.CreateInstance(__uuidof(HttpConnector));
printf("\nCreateInstance Method\n"); char szErrorTemp[100]; memset(szErrorTemp,0,sizeof(szErrorTemp));
sprintf(szErrorTemp,"\tFunction Return = %d\n", hr); printf(szErrorTemp);
printf("\n2.1.1\n");
Connector->Property["Timeout"] = "10000"; ////////// CODE ////////////////////////////////////////////////////
|
| Sign In·View Thread·PermaLink | 1.50/5 (2 votes) |
|
|
|
 |
|
|
The only think I can think of is that in my code if I was going ot use the httpconnector I used this code.....
#import "C:\\Program Files\\MSSoapSDK\\Binaries\\HLSC10.dll" raw_interfaces_only exclude("IStream","ISequentialStream","_LARGE_INTEGER","_ULARGE_INTEGER","tagSTATSTG","_FILETIME") . . . Connector.CreateInstance(__uuidof(HttpLibConnectorLib::HttpLibConnector));
and not a call to
leventozgur wrote: int hr = Connector.CreateInstance(__uuidof(HttpConnector));
You would then have to make sure that the hlcs10.dll file is on that Windows 2000 machine, but that SHOULD work for you.
Steve Maier, MCSD MCAD
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
i have developed a soap client using the high level interface and its working fine when i use webservices which return only one string back but if the webservice is returnning more than one complex data type it shows the result as "??????" here is my code where i call the webservice and process the response.
hr = m_pSoapClient->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispparams, &result, &ExceptInfo, NULL);
if(FAILED(hr)) { DisplayFault(_T("Invoke of method failed.")); } else { VariantChangeType(&result, &result, 0, VT_BSTR);//line to be checked // Display result. // m_ResultCtl.SetWindowText(CString(result.bstrVal)); ::MessageBox(NULL,CString(result.bstrVal),"HII",MB_OK); }
Any help would be highly appreciated Thanks Atul
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I am new to this SOAP and i down load that VC SOAP client code. i made some changes according to webservice. which shown below:
_variant_t vEndPoint = "http://localhost/WebService1/Service1.asmx"; _variant_t vAction = "http://tempuri.org/add"; BSTR method = L"add"; BSTR command = L"http://tempuri.org/add";
and in my server side is designed in C# and code is
[WebMethod] public int add(int a, int b) { int c=a+b; return c; }
RESULT from that is : 0.
If i am using this method [WebMethod] public string sum(string a) { return a; }
RESULT from that is: "Some thing wrong happen"
It very urgent, please i need a solution for that.
ravvikumaar.a
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Hi, Does the mssoap1.dll check wether the namespace schema url is really existing? This is my soap header. ------------------------ SOAP-ENV:Header eps:endpoints xmlns:eps="http://schemas.biztalk.org/btf-2-0/endpoints" SOAP-ENV:mustUnderstand="1" prop:properties xmlns:prop="http://schemas.biztalk.org/btf-2-0/properties" SOAP-ENV:mustUnderstand="1" prop:topic>root:ORDERS/SOAP-ENV:Header
--------------------------------------------------- But the dll throws an exception(_com_error). but If i change the url to some stupid name, then no exception, working fine. Can anybody pls clarify why this is hapenning? Plsss
Shehan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
As far as I can remember, it should not matter about the namespace. What is the exception you are getting?
Steve Maier, MCSD MCAD
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Actually u'r correct. But I found some other problem. I want to verify wether I'm correct. ok the problem is: If my message is properly received by the server( we use a customized jboss server), it returns a message saying "OK", but this is not a SOAP message, jusat a text message on HTTP.I checked this using a TCP monitor. Then it will raise an exception, but it is a number, no message. Does the mssoap1.dll expecting a return soap message? I think then it may be the broblem. If I send with wrong name spaces, then I'll get a return soap message with soap fault. Then the earlier com_error exception is not invoked. So I guess that dll is expecting a return soap message, if it is processed properly. Am I right? Pls, help me.
Shehan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi smpshehan, I want to read the SOAP header.But not able to implement Iheader interface. I request you can you please share your code or just give the guideline how to implement the IHeader interface. I am using SOAP.
Please help me.
Nit
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Can anybody give me the coding to create the above soap header using mssoap1.dll in VC++?
xmlns:eps="http://schemas.biztalk.org/btf-2-0/endpoints " SOAP-ENV:mustUnderstand="1"/> xmlns:prop="http://schemas.biztalk.org/btf-2-0/properties " SOAP-ENV:mustUnderstand="1"> root:ORDERS
My coding is as follows ------------------------------------------------ pSerializer->startHeader(_T("NONE")); int iMustUnderstand = 1;
pSerializer->startHeaderElement(_T("endpoints"), _T("http://schemas.biztalk.org/btf-2-0/endpoints"), iMustUnderstand, _T(""), _T("NONE"), _T("eps")); pSerializer->endHeaderElement(); pSerializer->startHeaderElement(_T("properties"), _T("http://schemas.biztalk.org/btf-2-0/properties"), iMustUnderstand, _T(""), _T("NONE"), _T("prop"));
iMustUnderstand = 0; pSerializer->startHeaderElement(_T("topic"), _T(""), iMustUnderstand, _T(""), _T("NONE"), _T("prop")); pSerializer->writeString(_T("root:ORDERS")); pSerializer->endHeaderElement();
pSerializer->endHeaderElement(); pSerializer->endHeader();
pSerializer->startBody(_T("NONE"));
pSerializer->writeXML((BSTR)sXMLContent);
pSerializer->endBody(); pSerializer->endEnvelope(); pConnector->EndMessage(); ---------------------------------------------------------- But my problem is that pConnector->EndMessage()gives an exception. When I change he above namespace urls to some odd ones ex:http://anyname.com, it deosn't throw that exception and work fine. what's wrong with that? Does the mssoap1.dll check wether the namesapce url is existing? Pls do reply me.
Shehan
Shehan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Can anybody give me the coding to create the above soap header using mssoap1.dll in VC++?
root:ORDERS
My coding is as follows ------------------------------------------------ pSerializer->startHeader(_T("NONE")); int iMustUnderstand = 1; pSerializer->startHeaderElement(_T("endpoints"), _T("http://schemas.biztalk.org/btf-2-0/endpoints"), iMustUnderstand, _T(""), _T("NONE"), _T("eps")); pSerializer->endHeaderElement(); pSerializer->startHeaderElement(_T("properties"), _T("http://schemas.biztalk.org/btf-2-0/properties"), iMustUnderstand, _T(""), _T("NONE"), _T("prop")); iMustUnderstand = 0; pSerializer->startHeaderElement(_T("topic"), _T(""), iMustUnderstand, _T(""), _T("NONE"), _T("prop")); pSerializer->writeString(_T("root:ORDERS")); pSerializer->endHeaderElement(); pSerializer->endHeaderElement(); pSerializer->endHeader(); pSerializer->startBody(_T("NONE")); pSerializer->writeXML((BSTR)sXMLContent); pSerializer->endBody(); pSerializer->endEnvelope(); pConnector->EndMessage(); ---------------------------------------------------------- But my problem is that pConnector->EndMessage()gives an exception. When I change he above namespace urls to some odd ones ex:http://anyname.com, it deosn't throw that exception and work fine. what's wrong with that? Does the mssoap1.dll check wether the namesapce url is existing? Pls do reply me.
Shehan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Shehan,
I am facin similar problem...
I am getting 401 (Auth. failed) error. Did you find any solution to this ?
Thanks, Amit.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
I try to execute VCSopeclient.exe that result appear "Something wrong happened !". Please help to tell me what's it up? Thank you very much.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|