How to add SOAP client functionality to native Win32 applications by using managed SOAP classes in Visual Studio .NET (908574)



The information in this article applies to:

  • Microsoft .NET Framework 1.1
  • Microsoft .NET Framework 1.0
  • Microsoft Visual Studio .NET (2003), Professional Edition
  • Microsoft Visual Studio .NET (2003), Enterprise Architect Edition
  • Microsoft Visual Studio .NET (2003), Enterprise Developer Edition
  • Microsoft Visual Studio .NET (2003), Academic Edition
  • Microsoft Visual Studio .NET (2002), Professional Edition
  • Microsoft Visual Studio .NET (2002), Enterprise Architect Edition
  • Microsoft Visual Studio .NET (2002), Enterprise Developer Edition
  • Microsoft Visual Studio .NET (2002), Academic Edition

INTRODUCTION

This article describes how to add SOAP client functionality to native Win32 applications by using managed SOAP classes.

MORE INFORMATION

This method is based on exposing Microsoft .NET Framework components to the Microsoft Component Object Model (COM). To access managed classes that are generated by using this method, do not use only the COM IDispatch interface from .NET Framework-based applications. Also use the IDispatch interface from all applications that are not based on the .NET Framework but use COM objects.

To use managed SOAP classes in native code, follow these steps:
  1. Use the Wsdl.exe utility to create a managed proxy class. To do this, open the Microsoft Visual Studio .NET 2003 Command Prompt window, and then type the following command:

    WSDL http://apps.gotdotnet.com/QuickStart/HelloWorld/HelloWorld.asmx?WSDL

  2. Create a new Microsoft Visual C# Class Library project. To do this, follow these steps:
    1. Start Visual Studio .NET 2003.
    2. On the File menu, click New, and then click Project.
    3. Click Visual C# Projects, and then click Class Library.
    4. In the Name box, type CSharpProxy, and then click OK.
  3. Replace the code in the Class1.cs file with the code that you generated in step 1. The code is similar to the following code sample.
    //------------------------------------------------------------------------------
    // <autogenerated>
    //     This code was generated by a tool.
    //     Runtime Version: 1.1.4322.2032
    //
    //     Changes to this file may cause incorrect behavior and will be lost if 
    //     the code is regenerated.
    // </autogenerated>
    //------------------------------------------------------------------------------
    
    // 
    // This source code was auto-generated by wsdl, Version=1.1.4322.2032.
    // 
    using System.Diagnostics;
    using System.Xml.Serialization;
    using System;
    using System.Web.Services.Protocols;
    using System.ComponentModel;
    using System.Web.Services;
    
    
    /// <remarks/>
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Web.Services.WebServiceBindingAttribute(Name="HelloWorldSoap", Namespace="http://tempuri.org/")]
    public class HelloWorld : System.Web.Services.Protocols.SoapHttpClientProtocol {
        
        /// <remarks/>
        public HelloWorld() {
            this.Url = "http://apps.gotdotnet.com/QuickStart/HelloWorld/HelloWorld.asmx";
        }
        
        /// <remarks/>
        [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/SayHelloWorld", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
        public string SayHelloWorld() {
            object[] results = this.Invoke("SayHelloWorld", new object[0]);
            return ((string)(results[0]));
        }
        
        /// <remarks/>
        public System.IAsyncResult BeginSayHelloWorld(System.AsyncCallback callback, object asyncState) {
            return this.BeginInvoke("SayHelloWorld", new object[0], callback, asyncState);
        }
        
        /// <remarks/>
        public string EndSayHelloWorld(System.IAsyncResult asyncResult) {
            object[] results = this.EndInvoke(asyncResult);
            return ((string)(results[0]));
        }
    }
    
  4. In Solution Explorer, right-click Class1.cs, and then click Rename.
  5. Type HelloWorld.cs, and then press ENTER.
  6. You must create a public interface and class to wrap the WSDL-generated code and to delegate the call. To do this, make changes in the proxy-generated class to make sure that all classes will be exposed in COM. To do this, follow these steps:
    1. Add the following using statement to the proxy-generated class:
      using System.Runtime.InteropServices;
    2. Add the following code example to the end of the HelloWorld class.
      public interface IHelloWorld 
      {
      	string SayHelloWorld();
      }
      
      
      [ComVisible(true)]    // By default, this value is true. However, this line of code is 
          // included for documentation purposes.
      public class WrapHelloWorld : IHelloWorld 
      {
       	public WrapHelloWorld() 
      	{
      	}
       	public string SayHelloWorld() 
      	{
      		HelloWorld ws = new HelloWorld();
      		return ws.SayHelloWorld();
      	}
       } 
      
    3. Press CTRL+SHIFT+B to build the solution.
  7. As soon as the Visual C# solution is built, you must register the DLL with COM. To do this, follow these steps:
    1. Open the Visual Studio .NET 2003 Command Prompt window.
    2. Move to the folder that contains the solution DLL.
    3. Type the following command, and then press ENTER:

      RegAsm.exe CSharpProxy.dll /tlb:CSharpProxy.tlb

    You can now use the generated CSharpProxy.tlb file in native code. The following code example illustrates how to use the CSharpProxy.tlb file in Visual C++.
    #include "stdafx.h"
    #import "CSharpProxy.tlb" raw_interfaces_only
    #include <iostream>
    #include <atlbase.h>
    
    using namespace CSharpProxy;
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	HRESULT hr = CoInitialize(NULL);
    	BSTR Val;
    	
    	IHelloWorldPtr ptrHW (__uuidof(WrapHelloWorld)); 
    	ptrHW>SayHelloWorld(&Val);
    
    	CW2A szResponse(Val);
    	cout << szResponse << endl;
    	::SysFreeString(Val);
    	CoUninitialize();
    	return 0;
    }

REFERENCES

For more information, visit the following Microsoft Developer Network (MSDN) Web sites: For more information about how to call a managed DLL from native C++ code, click the following article number to view the article in the Microsoft Knowledge Base:

828736 How to call a managed DLL from native Visual C++ code in Visual Studio .NET or in Visual Studio 2005

To obtain the SOAP Toolkit 3.0, visit the following Microsoft Web site:

Modification Type:MajorLast Reviewed:2/17/2006
Keywords:kbProgramming kbhowto kbinfo KB908574 kbAudDeveloper