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.
#include <wchar.h>
#import "XYSoapClient.dll";
using namespace XYSOAPCLIENTLib;
void main()
{
::CoInitialize(NULL);
IXYSoapClientPtr pSoapClient;
pSoapClient.CreateInstance( __uuidof(XYSoapClient));
try
{
_bstr_t sWSDL = L"http://myserver/mysvc/mysvc.wsdl";
_bstr_t sEmpty = L"";
if (pSoapClient->InitService(sWSDL, sEmpty, sEmpty, sEmpty))
{
_bstr_t sMethodName = L"GetData";
_variant_t sInput1 = L"First input";
_variant_t sInput2 = L"Second input";
_variant_t sRet = pSoapClient->InvokeMethod(sMethodName,
sInput1, sInput2);
wprintf(L"Output:\r\n\t%s", (const wchar_t*)((_bstr_t)sRet));
}
}
catch(...)
{
wprintf(L"Soap error:\r\n\t%s",
(const wchar_t*)pSoapClient->GetLastError());
}
pSoapClient.Release();
::CoUninitialize();
}
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.