Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Invoking web methods from a C++ console application

0.00/5 (No votes)
29 May 2003 1  
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