SOAP Toolkit 2.0: New Definition Languages Expose Your COM Objects to SOAP Clients

Carlos C. Tapang
This article assumes you�re familiar with XML, SOAP, COM, and Visual C++
Level of Difficulty     1   2   3 
SUMMARYIn SOAP Toolkit 2.0, the Services Description Language (SDL) has been replaced with the Web Services Description Language (WSDL) and the Web Services Meta Language (WSML). WSDL and WSML files describe the interfaces to a service and expose COM objects to SOAP clients. This article describes a custom tool, IDL2SDL, which takes an IDL file and produces WSDL and WSML files without waiting for a DLL or TLB file to be generated. Also shown is a customized development environment in which WSDL and WSML files automatically reflect the changes to IDL files.
W hen the November 2000 release of the Microsoft® SOAP Toolkit 1.0 became widely available, I wrote an Interface Description Language (IDL) to Service Description Language (SDL) translator, which I named IDL2SDL. Since SDL has been replaced with Web Services Description Language (WSDL) and Web Services Meta Language (WSML) in version 2.0 of the SOAP Toolkit, I have rewritten the translator to support WSDL and WSML. In this article I will explain how to use the translator and introduce version 2.0 of the SOAP Toolkit. You will get to know IDL2SDL and learn how to incorporate it into your development environment. The tool is available at https://www.infotects.com/IDL2SDL, together with a very simple C++ sample COM object on the server side and a Visual Basic®-based app on the client side. This tool is free, and I welcome questions and suggestions for improvement.

Why Translate IDL to SDL?

      The WSDL and WSML files describe the interfaces to your service and expose your COM object to SOAP clients. The SOAP Toolkit already provides the WSDLGenerator tool. The generator derives the service description from the object's TypeLib. (TypeLib is usually embedded in the DLL file in which a COM component resides.) Whereas the WSDLGenerator tool is very well-suited for situations in which you only want to reuse available components in a Web service, the IDL2SDL tool is more appropriate for situations in which you are designing your server components completely from the ground up.
      During development, interface specifications can change often, even during testing. The IDL2SDL utility allows you to change your IDL file and produce both WSDL and WSML files without having to wait for the DLL or TLB file to be generated. You can set up your development environment with IDL2SDL such that your WSDL and WSML files automatically reflect the changes to your IDL file. In a later section, I will describe the simple steps you need to take to make IDL2SDL part of the Visual Studio® development environment.
      Since SOAP is designed to be universal, it is applicable to remote procedure call component architectures other than COM. Likewise, IDL can express interface contracts for component architectures other than COM. There is no standard for IDL, but IDL2SDL can be modified to easily accommodate inputs for the Microsoft MIDL and for the DCE IDL compiler. The WSDLGenerator, however, is COM-specific.

Using IDL2SDL

      The syntax to invoke IDL2SDL is:
  IDL2SDL -w idlfile outdir serviceURL
The input IDL file is idlfile, outdir is the path to the directory pointed to by a Microsoft Internet Information Services (IIS) virtual directory where IDL2SDL will write the output files, and serviceURL is the URL for that same virtual directory. If the SOAP Toolkit 2.0 is properly installed on the machine running IIS, then IDL2SDL provides all the files you need to expose your C++ COM object to SOAP clients.
      For my sample, all output files are produced using the following invocation of IDL2SDL:
  IDL2SDL -w simple.idl c:\sample https://localhost/simple

The -w option enables WSDL output. The tool defaults to SDL output. Simple.idl is the input IDL file; c:\sample is the directory where IDL2SDL will write the output files; and the third parameter is the URI for the sample service.
      Figure 1 shows simple.idl, an example of an IDL file that IDL2SDL can accept. I will discuss other file formats shortly.

The WSDL File

      The IDL code in Figure 1 describes a sample COM component used throughout this article. I chose this bare-bones component to simplify the explanation of how you can use IDL2SDL with the SOAP Toolkit. In one method, the component adds two numbers and returns the sum; in another method, it converts all letters in an input string to upper case.
      To expose this component as a Web service, the two methods and all parameters must be described precisely, using a standard description language. WSDL is a language that describes services using well-formed XML. In the output WSDL file shown in Figure 2, the description for a single method is spread out among several sections of the file. Let's now take a look at exactly what each of these sections contains.
      The <message> section in the WSDL file describes the parameters and the return parameter, if any, in each method. Input parameters are specified as parts in an input message, and the return parameter is specified as the only part in an output message (suffixed by "Response").
      The <portType> section ties the operations to the messages, thereby abstractly describing each method in the simple COM object. For example, in the <message> section of Figure 2, the Add message describes two parameters, one each in a <part> element, operand1 and operand2. The AddResponse describes one part, the return value.
      In the <portType> section, the description of the Add method is precisely described by referring to the Add and AddResponse messages in the <operation name="Add"> element. At this point, the types of both input parameters and return values are specified, but the protocol to be used, the encoding, and other details are still unspecified. The IDL2SDL tool outputs one <portType> section for every interface definition found in the IDL file.
      The <binding> section specifies the protocol and encoding to be used for each operation. There can be several bindings pertaining to the same <portType> definition, but the IDL2SDL tool produces only one, for SOAP. Therefore, there is only one <binding> section for each interface.
      The <service> section contains one or more <port> subsections, one for each interface defined in the IDL file. Each <port> subsection has a "binding" attribute that points to the corresponding <binding> section. It also has a <soap:address> element that is a URI pointing to the only ASP file.
      If there were several interfaces defined in the same IDL file, there would be several <port> subsections; but each one of them would be pointing to the same ASP file. There is only one ASP file, reflecting the fact that all interfaces are implemented in the same module described by one set of WSDL and WSML files. (As of this writing, the WSDLGenerator generates one set of WSDL and WSML files for each interface, and the user can select only one interface per interactive session.)
      Normally, there should also be a <types> section in the file. You won't see one in Figure 2 because the input IDL file does not define new types. As of this writing, the WSDLGenerator tool generates the <types> section even if the component does not define new types.

The WSML File

      Neither the WSDL file (see Figure 3) nor the ASP file point to the COM module itself. The progID of the COM component is specified in the WSML file. Microsoft could have put all the information that is in the WSML file in the WSDL file (using extensibility elements), but having a separate WSML file provides an extra level of security. While the WSDL file may be public and can be made accessible to anyone, the WSML file can be locked up securely, like private keys versus public keys.
      The IDL2SDL tool produces only one WSML file for each IDL input, and so the possible different interfaces in each IDL file are output in the same WSML file in the form of separate <port> sections.

The ASP File

      The ASP file (see Figure 4) is required to forward the SOAP HTTP messages to the SoapServer COM object from the toolkit. The SoapServer then converts the HTTP request into a method call to the COM component specified in the WSML file, exactly as specified in the WSDL file.
      The ASP file that's produced is meant for testing only. The SoapServer object is optimized for staying in-cache. Therefore, for much better performance, you should not create the SoapServer object every time a service operation is invoked. Instead, you should create the SoapServer object in global.asa.

Using IDL2SDL in Visual C++

      Before I go into the details of how to make the sample service work with the toolkit, let me first describe the steps necessary to make IDL2SDL part of your Visual C++® development environment on a per-project basis. (I used the Visual C++ 6.0 Enterprise Edition development environment. There may be differences depending on the version of Visual C++ that you're using.)
  1. Click on the Project dropdown menu, then Settings (or press Alt-F7). In the Project Settings dialog, select Win32 Debug in the Settings For textbox.
  2. Expand the project in the listbox so that the IDL file appears. Select the IDL file and click on the General tab. Then click on the "Always use custom build step" checkbox in order to select it. This disables the MIDL compiler, which is reinstated in the next step.
  3. Click on the Custom Build tab. In the Commands edit box, type the following MIDL invocation to reinstate it:
        MIDL "$(InputDir)" /tlb "$(InputDir)\$(InputName).tlb" /h 
      "$(InputName).h" /iid "$(InputName)_i.c" /Oicf
    
    
  4. Below the MIDL invocation, type the following IDL2SDL invocation, and make sure that the IDL2SDL tool is located in a directory that is listed in the search paths.
        IDL2SDL -w "$(InputPath)" "$(InputDir)" 
                          https://localhost/simple 
    
    
  5. In the Outputs edit box, type the following two lines:
        $(InputDir)\$(InputName).h
      $(InputDir)\$(InputName).wsdl
    
    
This takes advantage of the dependency rules so that the WSDL file and other files are only recreated when the IDL file changes.

Creating the Sample IDL File

      To create the sample IDL file shown in Figure 1, you should follow these steps:
  1. Create an ATL project called Simple. Then use the ATL Object Wizard (ClassView, right-click on Simple Classes, and click New ATL Object).
  2. In the ATL Object Wizard dialog, select Simple Object and click Next. In the following dialog, type "Sample" as the name of the new object, and select the following attributes: Apartment Threading, Dual interface, and No Aggregation.
  3. Back in the ClassView window, right-click on the ISample interface and select Add Method in order to add the following two methods:
      HRESULT Add([in] long operand1, [in] long operand2, 
                [out,retval] long* 
                retVal);
    HRESULT ToUpper([in] BSTR inputString, [out,retval] BSTR* retVal);
    
    
  4. In the implementation file, Sample.cpp, add the include line #include <wchar.h>. Supply the following code to the Add method.
        *retVal = operand1 + operand2;
    
    
  5. Use the code shown in Figure 5 for the ToUpper method.
      Now you are ready to build the Simple.dll file.

Testing the Sample Component

      You can now use the toolkit to test the sample component as a SOAP service. If you haven't already done so, install the SOAP Toolkit on a machine that runs IIS. This machine will be used as both client and server. Follow these steps to test your component:
  1. On the server side, create a virtual directory using the IIS Manager. Name the virtual directory "Simple." Associate this virtual directory with the real directory where the files simple.wsdl, simple.wsml, and simple.asp reside. Make sure that the simple.dll file is registered.
  2. On the client side, save the following Visual Basic script in a file (testsample.vbs):
      set soapclient = CreateObject("MSSOAP.SoapClient") 
    Call soapclient.Init("https://localhost/simple/simple.wsdl", _
                         "SimpleService", "SamplePort") 
    wscript.echo soapclient.ToUpper("The quick brown fox jumped over")
    wscript.echo soapclient.Add(2,3) 
    On Error Resume Next 
    wscript.echo soapclient.faultcode 
    wscript.echo soapclient.faultstring 
    wscript.echo soapclient.faultactor 
    wscript.echo soapclient.detail
    
    
  3. Finally, to test the setup, from a command prompt type "cscript testsample.vbs".

Conclusion

      The sample Web service shown here demonstrates that version 2.0 of the SOAP Toolkit is a completely different implementation from version 1.0. However, it is just as easy to use. Like version 1.0, version 2.0 accommodates both users who just want to expose their COM object to SOAP and users who have a need to generate the SOAP messages. The IDL2SDL tool even makes it easier by automating the production of WSDL, WSML, and ASP files.
      The IDL2SDL tool is freely available, but it is not part of the SOAP Toolkit. This tool was built using the Flex lexical analyzer and the BISON parser generator, which are available from https://www.monmouth.com/~wstreett/lex-yacc/lex-yacc.html. The sample files and tools are also available from the Infotects Web site.
For background information see:
WSDL 1.0
Web Services: Building Reusable Web Components with SOAP and ASP.NET
Carlos C. Tapang is a senior software engineer at Infotects where he helps build client-server apps. Infotects is a professional services firm in Beaverton, OR that designs, builds, and supports quality technology solutions. You can reach Carlos at ctapang@infotects.com.

From the April 2001 issue of MSDN Magazine.