Using the WCF Moniker with COM Clients

 

This sample demonstrates how to use the Windows Communication Foundation (WCF) service moniker to integrate Web services into COM-based development environments, such as Microsoft Office Visual Basic for Applications (Office VBA) or Visual Basic 6.0. This sample consists of a Windows Script Host client (.vbs), a supporting client library (.dll), and a service library (.dll) hosted by Internet Information Services (IIS). The service is a calculator service and the COM client calls math operations—Add, Subtract, Multiply, and Divide—on the service. Client activity is visible in the message box windows.

System_CAPS_noteNote

The set-up procedure and build instructions for this sample are located at the end of this topic.

System_CAPS_importantImportant

The samples may already be installed on your computer. Check for the following (default) directory before continuing.

<InstallDrive>:\WF_WCF_Samples

If this directory does not exist, go to Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 to download all Windows Communication Foundation (WCF) and WF samples. This sample is located in the following directory.

<InstallDrive>:\WF_WCF_Samples\WCF\Basic\Services\Interop\COM

The service implements an ICalculator contract defined as shown in the following code example.

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [OperationContract]
    double Add(double n1, double n2);
    [OperationContract]
    double Subtract(double n1, double n2);
    [OperationContract]
    double Multiply(double n1, double n2);
    [OperationContract]
    double Divide(double n1, double n2);
}

The sample demonstrates the three alternative approaches for using the moniker:

  • Typed contract – The contract is registered as a COM visible type on the client computer.

  • WSDL contract – The contract is supplied in the form of a WSDL document.

  • Metadata Exchange contract – The contract is retrieved at runtime from a Metadata Exchange (MEX) endpoint.

To use the moniker with a typed contract use, appropriately attributed types for the service contract must be registered with COM. First, a client must be generated by using the ServiceModel Metadata Utility Tool (Svcutil.exe). Run the following command from a command prompt in the client directory to generate the typed proxy.

svcutil.exe /n:http://Microsoft.ServiceModel.Samples,Microsoft.ServiceModel.Samples http://localhost/servicemodelsamples/service.svc /out:generatedClient.cs

This class must be included in a project and the project should be configured to generate a COM-visible, signed assembly when compiled. The following attribute should be included in the AssemblyInfo.cs file.

[assembly: ComVisible(true)]

After building the project, register the COM-visible types by using regasm as shown in the following example.

regasm.exe /tlb:CalcProxy.tlb client.dll

The assembly that is created should be added to the Global Assembly Cache. Though not strictly required, this simplifies the process of the runtime locating the assembly. The following command adds the assembly to the Global Assembly Cache.

gacutil.exe /i client.dll
System_CAPS_noteNote

The service moniker requires only the type registration and does not use the proxy to communicate with the service.

ComCalcClient.vbs client application uses the GetObject function to construct a proxy for the service, using the service moniker syntax to specify the address, binding, and contract for the service.

Set typedServiceMoniker = GetObject(
"service4:address=http://localhost/ServiceModelSamples/service.svc, binding=wsHttpBinding, 
contractType={9213C6D2-5A6F-3D26-839B-3BA9B82228D3}")

The parameters used by the moniker specify:

  • The address of the service endpoint.

  • The binding that the client should use to connect with that endpoint. In this case, the system-defined wsHttpBinding is used though custom bindings can be defined in client configuration files. For use with the Windows Script Host, the custom binding is defined in a Cscript.exe.config file in the same directory as Cscript.exe.

  • The type of the contract that is supported at the endpoint. This is the type that was generated and registered above. Because Visual Basic script does not provide a strongly-typed COM environment, an identifier for the contract must be specified. This GUID is the interfaceID from CalcProxy.tlb, which can be viewed by using COM tools such as the OLE/COM Object Viewer (OleView.exe). For strongly-typed environments such as Office VBA or Visual Basic 6.0, adding an explicit reference to the type library and then declaring the type of the proxy object can be used in place of the contract parameter. This also provides IntelliSense support during client application development.

Having constructed the proxy instance with the service moniker, the client application can call methods on the proxy, which results in the service moniker infrastructure calling the corresponding service operations.

' Call the service operations using the moniker object
WScript.Echo "Typed service moniker: 100 + 15.99 = " & typedServiceMoniker.Add(100, 15.99)

When you run the sample, the operation response is displayed in a Windows Script Host message box window. This demonstrates a COM client making COM calls using the typed moniker to communicate with a WCF service. Despite the use of COM in the client application, the communication with the service consists only of Web service calls.

To use the moniker with a WSDL contract, no client library registration is required but the WSDL contract for the service must be retrieved through an out-of-band mechanism such as using a browser to access the WSDL endpoint for the service. The moniker can then access that contract at execution time.

The ComCalcClient.vbs client application uses the FileSystemObject to access the locally saved WSDL file and then again uses the GetObject function to construct a proxy for the service.

' Open the WSDL contract file and read it all into the wsdlContract string
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("serviceWsdl.xml", ForReading)
wsdlContract = objFile.ReadAll
objFile.Close

' Create a string for the service moniker including the content of the WSDL contract file
wsdlMonikerString = "service4:address='http://localhost/ServiceModelSamples/service.svc'"
wsdlMonikerString = wsdlMonikerString + ", binding=WSHttpBinding_ICalculator, bindingNamespace='http://Microsoft.ServiceModel.Samples'"
wsdlMonikerString = wsdlMonikerString + ", wsdl='" & wsdlContract & "'"
wsdlMonikerString = wsdlMonikerString + ", contract=ICalculator, contractNamespace='http://Microsoft.ServiceModel.Samples'"

' Create the service moniker object
Set wsdlServiceMoniker = GetObject(wsdlMonikerString)

The parameters used by the moniker specify:

  • The address of the service endpoint.

  • The binding that the client should use to connect with that endpoint and the namespace in which that binding is defined. In this case, the wsHttpBinding_ICalculator is used.

  • The WSDL that defines the contract. In this case this is the string that has been read from the serviceWsdl.xml file.

  • The name and namespace of the contract. This identification is required because the WSDL may contain more than one contract.

    System_CAPS_noteNote

    By default, WCF services generate separate WSDL files for each namespace that the use. These are linked with the use of the WSDL import construct. Because the moniker expects a single WSDL definition, the service must either use a single namespace as demonstrated in this sample or the separate files must be manually merged.

Having constructed the proxy instance with the service moniker, the client application can call methods on the proxy, which results in the service moniker infrastructure calling the corresponding service operations.

' Call the service operations using the moniker object
WScript.Echo "WSDL service moniker: 145 - 76.54 = " & wsdlServiceMoniker.Subtract(145, 76.54)

When you run the sample, the operation response is displayed in a Windows Script Host message box window. This demonstrates a COM client making COM calls using the moniker with a WSDL contract to communicate with a WCF service.

To use the moniker with a MEX contract, as with the WSDL contract, no client registration is required. The contract for the service is retrieved at execution time through the internal use of Metadata Exchange.

The ComCalcClient.vbs client application again uses the GetObject function to construct a proxy for the service.

' Create a string for the service moniker specifying the address to retrieve the service metadata from
mexMonikerString = "service4:mexAddress='http://localhost/servicemodelsamples/service.svc/mex'"
mexMonikerString = mexMonikerString + ", address='http://localhost/ServiceModelSamples/service.svc'"
mexMonikerString = mexMonikerString + ", binding=WSHttpBinding_ICalculator, bindingNamespace='http://Microsoft.ServiceModel.Samples'"
mexMonikerString = mexMonikerString + ", contract=ICalculator, contractNamespace='http://Microsoft.ServiceModel.Samples'"

' Create the service moniker object
Set mexServiceMoniker = GetObject(mexMonikerString)

The parameters used by the moniker specify:

  • The address of the service metadata exchange endpoint.

  • The address of the service endpoint.

  • The binding that the client should use to connect with that endpoint and the namespace in which that binding is defined. In this case, the wsHttpBinding_ICalculator is used.

  • The name and namespace of the contract. This identification is required because the WSDL may contain more than one contract.

Having constructed the proxy instance with the service moniker, the client application can call methods on the proxy, which results in the service moniker infrastructure calling the corresponding service operations.

' Call the service operations using the moniker object
WScript.Echo "MEX service moniker: 9 * 81.25 = " & mexServiceMoniker.Multiply(9, 81.25)

When you run the sample, the operation response is displayed in a Windows Script Host message box window. This demonstrates a COM client making COM calls using the moniker with a MEX contract to communicate with a WCF service.

To set up and build the sample

  1. To build the C# or Visual Basic .NET edition of the solution, follow the instructions in Building the Windows Communication Foundation Samples.

  2. From a Visual Studio command prompt, open the \client\bin folder, under the language-specific folder.

    System_CAPS_noteNote

    If you are using Windows Vista, Windows Server 2008, Windows 7, or Windows Server 2008 R2, make sure that you run the command prompt with administrator privileges.

  3. Type in tlbexp.exe client.dll /out:CalcProxy.tlb to export the dll to a tlb file. A "Type library exporter warning" is expected but is not an issue because the generic type is not required.

  4. Type in regasm.exe /tlb:CalcProxy.tlb client.dll to register the types with COM. A "Type library exporter warning" is expected but is not an issue because the generic type is not required.

  5. Type in gacutil.exe /i client.dll to add the assembly to the Global Assembly Cache.

To run the sample on the same computer

  1. Test that you can access the service using a browser by typing in the following address: http://localhost/servicemodelsamples/service.svc. A confirmation page should be displayed in response.

  2. Run ComCalcClient.vbs from \client, from under the language-specific folder. Client activity is displayed in message box windows.

  3. If the client and service are not able to communicate, see 8787c877-5e96-42da-8214-fa737a38f10b.

To run the sample across computers

  1. On the service computer, create a virtual directory named ServiceModelSamples. The Setupvroot.bat script included with the sample can be used to create the disk directory and virtual directory.

  2. Copy the service program files from %SystemDrive%\Inetpub\wwwroot\servicemodelsamples to the ServiceModelSamples virtual directory on the service computer. Be sure to include the files in the \bin directory.

  3. Copy the client script file from the \client folder, under the language-specific folder, to the client computer.

  4. In the script file, change the address value of the endpoint definition to match the new address of your service. Replace any references to "localhost" with a fully-qualified domain name in the address.

  5. Copy the WSDL file to the client computer. In the WSDL file, serviceWsdl.xml, replace any references to "localhost" with a fully-qualified domain name in the address.

  6. Copy the Client.dll library from the \client\bin folder, under the language-specific folder, to a directory on the client computer.

  7. From a command prompt, navigate to that destination directory on the client computer. If using Windows Vista or Windows Server 2008, make sure to run the command prompt as Administrator.

  8. Type in tlbexp.exe client.dll /out:CalcProxy.tlb to export the dll to a tlb file. A "Type library exporter warning" is expected but is not an issue because the generic type is not required.

  9. Type in regasm.exe /tlb:CalcProxy.tlb client.dll to register the types with COM. Ensure that path has been set to the folder that contains regasm.exe before you run the command.

  10. Type in gacutil.exe /i client.dll to add the assembly to the Global Assembly Cache. Ensure that path has been set to the folder that contains gacutil.exe before you run the command.

  11. Test that you can access the service from the client computer using a browser.

  12. On the client computer, launch ComCalcClient.vbs.

To clean up after the sample

  • For security purposes, remove the virtual directory definition and permissions granted in the setup steps when you are finished with the samples.


Show: