Click here to Skip to main content
Licence 
First Posted 1 Jan 2003
Views 717,593
Bookmarked 80 times

Invoking web methods from a C++ console application

By | 29 May 2003 | Article
A simple COM component to access various web services

Introduction

It seems that we programmers will never catch up with all the new technologies out there, no matter how hard we try. At first we simply ignore them. .NET? No thank you, my C++ programs or COM components can do everything I need. Gradually, some new technologies will disappear, while others will become even more popular despite the fact that we still don't like them. Now it's time for us to find out what's so great about this new technology and what it can do for us. The scary thing is, we may have to learn and use a new technology because it can do some new things or it does old things better than what we have being using. Sometimes, we are simply told to learn and use a new technology, after all we are just programmers.

One thing I like about .NET is that writing a web service is made so easy with ASP.NET. I just hope using a web service is made easier. To use a web service within .NET code, you need to generate a proxy class using a tool such as the wsdl.exe program and compile this generated class into your program. You will have to generate and compile 10 proxy classes, if your program needs to access 10 different web services. What about using a .NET web service outside of .NET? Well, you can use objects in Microsoft SOAP Toolkit to access a web service. However, the sample code provided by Microsoft is mainly for VB programmers. My goal is to develop a simple, flexible, and reusable COM component, that can access various web services and it has to be easy to use in C++ programs.

My COM component depends on the SoapClient object from the Microsoft SOAP Toolkit 3.0 (you may also choose to use Soap Toolkit 2.0). The SoapClient object is pretty simple by itself, but using it within a C++ program can be tricky, because it "binds" to a web service at runtime. The COM component I developed is contained in XYSoapClient.dll, it uses SoapClient internally but is more flexible and powerful, and you can use it easily from C++ programs. You can even use it in C programs. The best part is, you don't need to generate and compile a proxy class, every time you want to use a different web service!

The XYSoapClient.dll component

This is a regular COM DLL which contains the XYSoapClient object. You need to register this DLL on the local machine before using it. You also need to install Microsoft SOAP Toolkit 3.0 (or 2.0). Typically, you create an instance of XYSoapClient in your code and call the InitService method, passing the URL for the web service you want to access, then call the InvokeMethod method to invoke the web method with given name. If you want to access a different web service later, just create another XYSoapClient object and repeat the above actions. You can also use multiple XYSoapClient objects to access different web services simultaneously in your code.

Here are the public methods of the XYSoapClient object.

BOOL InitService(BSTR WSDL, BSTR ServiceName, BSTR Port, BSTR WSML);

This method is called to initialize the object for a specific web service. The return value indicates success or failure. The WSDL parameter is the URL for the WSDL file of the web service. The parameters ServiceName, Port , and WSML are optional (with empty strings as default values). This method has to be called before invoking any web method.

BOOL SetClientProperty(BSTR PropName, VARIANT PropValue);

This method sets the SOAP client property. PropName is the name of the client property to set and PropValue is the new value. The return value indicates success or failure. For details, see the documentation for the SoapClient object in Microsoft SOAP Toolkit.

BOOL SetConnectorProperty(BSTR PropName, VARIANT PropValue);

This method sets the SOAP connector property. PropName is the name of the connector property to set and PropValue is the new value. This method can only be called after calling the InitService method. You need to set connector properties ProxyServer and ProxyPort, if there is a firewall between your code and the web server machine that runs the web service. You need to set connector properties AuthUser and AuthPassword, if the web service requires client authentication. For details, see the documentation for the SoapClient object in Microsoft SOAP Toolkit.

BSTR GetLastError();

This method returns an error description string, for the last action on the current object (empty if there is no error).

VARIANT InvokeMethod(BSTR MethodName, VARIANT Input1, VARIANT Input2, VARIANT Input3, VARIANT Input4, VARIANT Input5);

Call this method to invoke a web method with given name. MethodName is the name of the method to be invoked. You can specify up to 5 optional parameters. This method can only be called after calling the InitService method.

BSTR SetSoapToolkitVersion(BSTR sVersion);

By default, this component uses Microsoft SOAP Toolkit 3.0. You can use version 2.0 instead, if you call this method passing "2.0" as the parameter. The return value is the previous version string.

Limitations

As you can see, when using XYSoapClient to access a web service, the number of input parameters of a web method is limited to five. You can easily increase this limit by modifying the code yourself. The types of the input and output are restricted to types that can be represented as VARIANT.

Sample code

Here is a complete C++ console application that uses XYSoapClient, to invoke a web method. We assume the web method is named GetData, it takes two string arguments and returns a string as output.

/************* TestApp.cpp *******************/
#include <wchar.h>
#import "XYSoapClient.dll";
using namespace XYSOAPCLIENTLib;

void main()
{
    // initialize com
    ::CoInitialize(NULL);
    // declare a smart pointer for the XYSoapClient type
    IXYSoapClientPtr pSoapClient;
    // create an XYSoapClient object
    pSoapClient.CreateInstance( __uuidof(XYSoapClient));
    try
    {
        // the url for the WSDL file of the web service
        _bstr_t sWSDL = L"http://myserver/mysvc/mysvc.wsdl";
        // the empty string (as default values)
        _bstr_t sEmpty = L"";
        // call InitService
        if (pSoapClient->InitService(sWSDL, sEmpty, sEmpty, sEmpty))
        {
            // the name of the method to be invoked
            _bstr_t sMethodName = L"GetData";
            // the input strings
            _variant_t sInput1 = L"First input";
            _variant_t sInput2 = L"Second input";
            // invoke the method
            _variant_t sRet = pSoapClient->InvokeMethod(sMethodName, 
                                                        sInput1, sInput2);
            // print the output string
            wprintf(L"Output:\r\n\t%s", (const wchar_t*)((_bstr_t)sRet));
        }
        
        // add code to call another web service
        // ...
    }
    catch(...)
    {
        // unexpected soap error
        wprintf(L"Soap error:\r\n\t%s", 
                (const wchar_t*)pSoapClient->GetLastError());
        // add more error handling code
        // ...
    }
    // clean up the XYSoapClient object
    pSoapClient.Release();
    // uninitialize com
    ::CoUninitialize();
}
/************* End of TestApp.cpp *******************/

This article also includes a generic console application XYSoapClientApp.exe, that can be used to access any web method from the command line, as long as the input and output of the web method are strings. The syntax to use this application from command line is:

XYSoapClientApp.exe ServiceURL MethodName [Input1 
                    [Input2 [Input3 [Input4 [Input5]]]]]

The following command will be equivalent to executing the above console application, TestApp.exe.

XYSoapClientApp.exe "http://myserver/mysvc/mysvc.wsdl" "GetData" 
                                    "First input" "Second input"

Also, since XYSoapClient is a regular COM object, there is nothing to prevent you from using it in VB (script) programs and ASP pages. Note that when using it in ASP pages, you need to set the SOAP client property ServerHTTPRequest to true, by calling the SetClientProperty method (before you call the InitService method). Comparing to the SoapClient object in Microsoft SOAP Toolkit, you have the flexibility of not knowing the names of the web methods, when writing your VB (script) code using XYSoapClient.

About the source code

XYSoapClient is implemented using the C++ class XYDispDriver, described in another CodeProject article, (the source code is included with this article). This class allows you to dynamically create and use COM objects in C++ programs. The source code of XYSoapClient is in the file XYSoapClient.zip.

Thank you for reading my article.

Update History

  • May 30, 2003: Updated source code for XYSoapClient.dll. The previous version of XYDispDriver.cpp does not handle array and reference types properly.
  • Mar 20, 2003: The source code is modified so that, it uses Microsoft SOAP Toolkit 3.0 by default. The method SetSoapToolkitVersion is added, so that you can choose version 2.0 if that is the only version installed on your machine. It is no longer necessary to use or download code for XYSoapClient30.dll.
  • Mar 13, 2003: The source code for XYSoapClient30.dll has been uploaded. Click here to get it. As I said, the difference with the current version is only in a few id and name strings.
  • Jan 30, 2003: Modified XYSoapClient.dll so that you can set SOAP client properties before calling the InitService method.
  • Jan 23, 2003: Added another binary file XYSoapClient30.dll. This is identical to XYSoapClient.dll, except that you need to install Microsoft Soap Toolkit version 3.0 (instead of version 2.0) before using it. These two COM components have the same interface and can coexist on the same machine.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Xiangyang Liu 刘向阳



United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralWebservice call failure Pinmemberjonsunggyu0:27 3 Jun '11  
GeneralRe: Webservice call failure PinmemberXiangyang Liu 刘向阳3:05 3 Jun '11  
GeneralThe function returns Soap error: Connector:Connection time out. PinmemberBattosaiii1:23 8 Feb '10  
GeneralMany thanks to author... Great work!! PinmemberDec123419:44 2 Jun '09  
GeneralI want to pass as a parameter a structure PinmemberThomas_Mathews19:16 20 Jan '09  
GeneralI want to pass one complex argument when calling webservice method. PinmemberThomas_Mathews23:56 19 Jan '09  
GeneralPassing / Receiving objects Pinmembervikman5:06 3 Jan '07  
Questionhow to connect to a proxy server Pinmemberbreakpoint21:55 16 Aug '06  
Questionhow to set the timeout of the web service Pinmemberbreakpoint23:56 28 Jul '06  
AnswerRe: how to set the timeout of the web service PinmemberDec123419:42 2 Jun '09  
Generalpassing structure as parameter Pinmembercesarfernandez5:08 28 Dec '05  
GeneralRe: passing structure as parameter PinmemberXiangyang Liu10:42 28 Dec '05  
GeneralRe: passing structure as parameter Pinmembercesarfernandez21:02 28 Dec '05  
QuestionIf I want to return a DataSet, How to do it? PinmemberRoland Liu17:15 20 Oct '05  
AnswerRe: If I want to return a DataSet, How to do it? PinmemberXiangyang Liu3:40 22 Oct '05  
GeneralDifferent returned type Pinmemberjoujou662:31 16 Sep '05  
GeneralRe: Different returned type PinmemberXiangyang Liu5:16 16 Sep '05  
GeneralCreateInstance doesn't works Pinmemberjoujou660:29 16 Sep '05  
GeneralRe: CreateInstance doesn't works Pinmemberjoujou662:23 16 Sep '05  
GeneraldateTime type as the invoke function parameter Pinmembervberi@viqsolutions.com10:52 18 Aug '05  
My Web Server waiting the dateType parameter . I was trying to try something like
double dvalue = rawtime;
_variant_t datevalue(dvalue, VT_DATE);, but it's coming with the
"Invalid number of arguments
Soap error:
SoapMapper:Saving SoapMapper scheduleddate failed"
How can I escape from that error?
GeneralRe: dateTime type as the invoke function parameter PinmemberXiangyang Liu14:13 18 Aug '05  
GeneralRe: dateTime type as the invoke function parameter PinsussAnonymous5:29 22 Aug '05  
GeneralRe: dateTime type as the invoke function parameter PinsussAnonymous2:51 22 Aug '05  
GeneralSoapClient::GetLastError does not return an error Pinmemberavner_simon5:47 18 Jul '05  
GeneralPassing array parameter Pinsussmehdi_tn22:27 12 Jul '05  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120529.1 | Last Updated 30 May 2003
Article Copyright 2003 by Xiangyang Liu 刘向阳
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid