Integrating WCF Services with COM+
Revised August 2007
Microsoft .NET Framework 3.0
Microsoft Internet Information Services
Microsoft Visual Studio 2005
Summary: This article will detail step by step instructions to consume COM+ application services from WCF clients. We will also discuss how legacy applications can use applications that expose WCF services built on .NET 3.0. The content for this article is based on Chapter 10 of Pro WCF : Practical Microsoft SOA Implementation by APress. This book is targeted towards beginner to intermediate readers and part of Apress series that discusses WPF, WCF and WF. (30 printed pages)
- Integrating WCF Services with COM+
- Running a COM+ Application as a WCF Service
- COM+ Application WCF Service Wrapper
- Using SvcConfigEditor.exe Utility
- Using ComSvcConfig.exe Utility
- Client Proxy Generation
- Visual Basic 6 COM+ Hiding Interfaces
- .NET Enterprise Services and COM+ Components
- Client Proxy generation
- COM+ Application WCF Service Wrapper
- Consuming WCF Services from COM+
- Typed Contract Service Moniker
- Metadata Exchange Contract Service Moniker
- WSDL Contract Service Moniker
Introduced in 1993, Component Object Model (COM) was the basis for other emerging technologies from Microsoft such as Object Linking and Embedding (OLE), ActiveX, and Distributed COM (DCOM). COM was initially introduced to compete with Common Object Request Broker Architecture (CORBA), a language-independent and cross-platform distributed system technology. They did share some core principles, but they were not compatible. Concepts and techniques such as Interface Definition Language (IDL) are present in both technologies. However, binary interoperability didn’t exist.
COM+, introduced in 1998, was more of ancillary technology that was built on COM but did not replace it. Key features of COM+ are transactional components, queued components, role-based security, and object pooling. COM+ 1.5 added features such as application pooling, SOAP services, services without components, and some other features . Not without faults, numerous applications were developed based upon this component technology. As a result, we can’t ignore the existing investment by enterprises in this technology. It would damage Microsoft’s credibility and the marketability if Microsoft introduced a new technology that would force an enterprise to scrap its original investments. Therefore, Microsoft and the WCF team worked hard to provide an evolutionary, as opposed to revolutionary, approach for bridging the technological divide, never forgetting the famous quote “Those who cannot remember the past are condemned to repeat it.” (Attributed to George Santayana, 19th-century philosopher)
Today, COM+ 1.5 is a core part of the Windows platform. Even with the .NET base class library (BCL) COM interoperability still occurs. Runtime callable wrappers (RCW) are used throughout the .NET BCL—one prime example in .NET 3.0 is the web browser Control, which is, as stated in the MSDN documentation, a managed wrapper for the web browser ActiveX control. Additionally, serviced components use COM+ transactions.
Why Integrate with COM+?
Although the future of the Windows platform is destined to be managed code, COM+ will still be around. COM exists in the core Windows platform in addition to the Win32 API (that has gone legacy) but still exists and matures. However, the key concern is the billions of lines of code that independent software developers have written to produce solutions. A great number of solutions have been built on COM+ by enterprises that have also spent billions of dollars on them. Therefore, clearly WCF needs to work with legacy implementations in order to justify an investment in extending existing applications.
Few applications built today are completely stand-alone. In fact, the terms application and solution need a little definition. Generally, an application represents a stand-alone deployable set of components, functionality, and so on. A solution, however, represents a combination of applications coupled together (either tightly or loosely) to address numerous business-processing requirements.
Therefore, today we need to build solutions. These solutions will most likely require integration with existing data and processes that exist in legacy technology, where some of that technology will be COM+. We should also consider that the existing COM+ applications aren’t going to be thrown away and rewritten in .NET and WCF. Since we’re building all these new applications based upon .NET and they’ll of course offer fantastic services that you’ll just need to share, you’ll need a way to provide legacy COM+ applications to call your services, just as any other application would. Fortunately, the WCF team has provided the core tools to facilitate both sides of the interoperability needs.
Note: We refer to QuickReturns Ltd several times in this article. QuickReturns Ltd is a fictitious case study to illustrate WCF business drivers and technical advancements. Please download it from the links at the start and the article and familiarize yourself with the business case.
Running a COM+ Application As a WCF Service
Let’s take a look at a scenario involving QuickReturns Ltd.’s Old Horse position-tracking system (or a custody system). Old Horse was built in the late 1990s using Visual Basic 6. Since other groups within QuickReturns Ltd. leverage Old Horse, the Old Horse development team provided COM interfaces allowing client applications to interoperate with Old Horse using COM+.
When an Asset Manager makes a trade, it’s necessary that the trade information is posted to the custody system. Additionally, as you’ll see later, it’s necessary that the custody system checks with the Asset Manager’s system for pricing and pending trade information.An overview of what the solution architecture is shown in figure 10-1 below.
Figure 10-1. QuickReturns Ltd.’s Old Horse system
Visual Basic 6 COM+ Component Sample Setup
The example we’ll use is a simple Visual Basic 6 COM (ActiveX DLL) component that exposes two interfaces. The complete solution is contained in accompanying sample code within the Example1 folder. The following code snippets are just the method signatures representing the Visual Basic 6 COM interface. This is an illustration of a Visual Basic 6 component and should not be viewed as best Visual Basic 6 best practice.
When looking at Visual Basic 6 COM components, you’ll soon see that some issues relate to how the WCF interfaces leverage type library information in regard to COM+ application components. Visual Basic 6 COM packs both the component logic and the type library information inside the COM DLL; doing so adds some attributes that prevent some interfaces from being initially wrapped in WCF COM+ integration.
Prior to working through this example, set up a virtual directory in IIS called VB6ComSample that is set for ASP.NET 2.0 and has anonymous access enabled (you can run the script CreateVirtualDirs.bat located in the Example1 samples directory to setup IIS for you).
The PositionManagement interface shown in Listing 10-1 provides a set of simple methods that allow the retrieval of the position for a given ticker, in addition to providing a method for updating the persisted quantity associated with a ticker. One element that is not shown is a constructor. COM+ objects don’t offer a constructor. They can provide information in other ways, such as with an initialization method. Visual Basic 6 and COM offer several ways of providing static configuration information such as COM+ Initialization strings on the configured component; however, that requires implementing IObjectConstructString in Visual Basic 6 and using the ConstructionEnable attribute in .NET. For the example code and to keep it simple, we’re just showing method interfaces. The ability to provide a connection string on object construction would be something that could be provided through COM+ initialization.
Listing 10-1. PositionManagement.cls
The second component is the Position component. This class represents mostly a data class with read/write properties. In addition, it has two methods; one provides a retrieval of a specific position for a ticker, and the other returns a concrete Position object for a specific ticker. Listing 10-2 shows the abbreviated class, and the full class is part of the article code in \OldHorsePositionTracking\VB6\PositionManagement.
Listing 10-2. Visual Basic 6 Position Class: Position.cls
|Visual Basic 6 Position Class: Position.cls||Copy Code|
One additional aspect of the PositonManagement class is that it’s configured in Visual Basic 6 to be an MTS component with a Required transaction setting. This setting is reflected in the generated WCF service inside the configuration file and is handled automatically by the COM+ Integration Wizard, which makes a call to the ComSvcConfig.exe utility. This allows flow from a WCF client to your COM+ component, ultimately being managed by the Microsoft Distributed Transaction Coordinator (MSDTC).
Once the project is built to an ActiveX DLL, it is ready to be installed and configured as a COM+ application. Briefly, for a Visual Basic 6 COM component, you follow these steps to create the OldHorse COM+ application: (We won’t go into too much depth on how to create Visual Basic 6 COM+ applications. Note that these steps for COM+ applications are programmable through the COM Administration type library. However, .NET offers the RegSvcs.exe utility that provides a simple command-line interface for this.)
First, from Administrative Tools, launch Component Services. Alternatively you can also get to this Microsoft Management Console (MMC) via the dcomcnfg.exe command. Then, expand the Component Services node until you are at the computer you want to configure for your COM+ application. In this example, it’s the local machine, or My Computer. Select the COM+ Applications object in the console, right-click, and choose New Application, as shown in Figure 102.
Figure 10-2. Creating a new COM+ application
At this point you’re presented with the COM+ Application Install Wizard. Click through the first page of the wizard. On the second page, click the Create an Empty Application button, as shown in Figure 10-3.
Figure 10-3. Creating an empty COM+ application
On the next page of the wizard, enter the name of your application, and ensure you select Library Application as the activation type (see Figure 10-4).
Figure 10-4. OldHorse library activation
Click through the last page of the wizard. At this point, you should now have a COM+ application defined in Component Services. However, this is an empty package and has no associated components.
The next step is to add your compiled ActiveX DLL into the package. Do that by first selecting the Components tree from within the OldHorse COM+ application. Right-click the Components folder under the OldHorse application, and then choose New | Component, as shown in Figure 10-5.
Figure 10-5. Adding a new component to the OldHorse application
This opens the COM+ Component Installation Wizard. Click Next in the wizard, and then choose Install New Component(s). Then, navigate to where your Visual Basic 6 COM component’s DLL resides (if you have extracted the samples, it is located in the directory \OldHorsePositionTracking\VB6\PositionManagement). Choose it, and then just click Next until the wizard is dismissed.
At this point you should have a COM+ application with the components shown in Figure 10-6.
Figure 10-6. Configured OldHorse COM+ application
First, you’ll see two components each with a single interface listed—the name manufactured by the Visual Basic 6 framework. Second, in the right pane, notice the Required transaction attribute. (You can see this view by clicking the detail view.) This attribute forces the activation of this component within a COM+ transaction—either a new transaction or an inherited transactional context from the caller.
COM+ Application WCF Service Wrapper
Once a COM+ application is configured, you’re ready to leverage WCF’s utilities for creating the necessary resources for calling a COM+ component from a WCF client. The primary utility for this is the ComSvcConfig.exe utility. This is a command-line utility that is installed with the .NET 3.0 runtime. Additionally, the SvcConfigEditor.exe utility provides a graphical interface with some additional features that help hide the complexities of the command-line ComSvcConfig.exe utility. One suggestion is to get used to the SvcConfigEditor.exe utility; it facilitates the composition of proper configuration files for WCF with configuration-time validation of many elements.
Using SvcConfigEditor.exe Utility
Before you proceed, it’s important to understand some caveats related to COM+ interoperability with WCF. There are restrictions as to what COM+ interfaces can be exposed as a web service through the COM+ Integration layer. Those restrictions are listed in the SDK, but some of them are as follows:
- Interfaces that pass object references as parameters: This violates a core tenet of SOA in that passing a reference across a service boundary is expensive.
- Interfaces that pass types that are not compatible with the .NET Framework COM Interop conversions: This is a general incompatibility issue for types that won’t serialize between the interoperability layers.
- Interfaces for applications that have application pooling enabled when hosted by COM+: This causes multiple listeners on the same URI moniker issues because there will be more than one application pool attempting to reserve the service endpoint address.
- Interfaces from managed components that have not been added to the Global Assembly Cache: This is a general limitation of how COM+ hosts configured managed components. There are other means of using COM+ from managed applications (services without components were introduced in COM+ 1.5 ), but they are not supported with WCF COM+ integration.
The first item mentioned here is important because given that one of the core tenets of SOA is that boundaries are explicit, it would be expensive to share an interface pointer across the service boundary. Also, given that the default WCF service behavior InstanceContext mode is PerCall, this is something your SOA implementation should consider.
In addition to the previously listed limitations, you’ll soon see some limitations with Visual Basic 6 components and, specifically, how Visual Basic 6 components are implemented.
At this point, you’re ready to create a WCF interoperability layer around your COM+ components. Start by launching the SvcConfigEditor.exe utility, which is located in the Microsoft SDK’s Bin directory. The easiest way is to launch the CMD shell shortcut that gets installed on your Start menu under the Microsoft Windows SDK program group or from within Visual Studio 2005 Tools menu as WCF Service Configuration Editor.
Start with no configuration file, and have the utility generate the necessary parts; this will allow you to call the OldHorse component from a WCF client.
From the menu bar of SvcConfigEditor.exe, select File | Integrate | COM+ Application. At this point you should see a listing of all the COM+ applications, including OldHorse, that are present on the local machine.
Figure 10-7. COM+ Integration Wizard
If you expand the OldHorse.PositionManagement node until you are able to see the list of interfaces (which will only be one), then select the _PostionManagement interface, and click Next. At this point, you should see the page shown in Figure 10-8.
Figure 10-8. _PositionManagement interface
Keep all selected, and just click Next. This presents the Hosting Mode options. Choose the web hosting in-process mode, which allows per-message activation and hosting within the IIS/WAS worker process. The other hosting options are not available for library-activated (in-process) applications and are enabled when the activation type is Server Activated (out-of-process). Ensure that the Add MEX endpoint option is enabled. This allows clients to leverage WS-Metadata Exchange to query the interface for contract and service information.
The next page of the wizard lists the IIS virtual directories on the local machine. Make sure you choose an IIS virtual directory that is configured for the relevant .NET Framework. For this example, we’ve preconfigured a virtual directory called /localhost/VB6ComSample (see Figure 10-9) that is configured for ASP.NET 2.0.
Figure 10-9. Choosing an IIS virtual directory
At that point, click Next, and you’re presented with the summary of options shown in Figure 10-10.
Figure 10-10. COM+ integration summary page
Click Next again, and the SvcConfigEditor.exe makes a call to the ComSvcConfig.exe utility with the appropriate command-line options. This generates two files in the virtual directory. If the SvcConfigEditor.exe utility cannot find the ComSvcConfig.exe utility, you’ll be presented with a message box asking you to specify where it can be located (by default the ComSvcConfig.exe utility is located at %SystemRoot% \Microsoft.NET\Framework\v3.0\Windows Communication Foundation directory)
The two resources that are generated provide the WCF wrapper service resource file and a Web.config file. The WCF service file is generated with the COM ProgID as the filename. For this example, the component OldHorse.PositionManagement generates a file OldHorse.PositionManagement.svc. The contents of that file appear in Listing 10-3.
Listing 10-3. OldHorse.PositionManagement.svc
|[CodeLanguage table header]||Copy Code|
The SVC file contains a single line that points to the service factory that will provide the COM+ integration—WasHostedComPlusFactory. The second parameter, Service, provides two initialization parameters for the factory class. The first is the GUID for the COM interface as specified by the type library for the COM component. If you leverage a tool such as OleView (which comes with the Windows SDK), view the type library for OldHorse, and dump the IDL, you’ll see that the supplied GUID matches the UUID of the implementation class, which is PositionManagement.
The second parameter represents the COM+ application ID, which is visible by choosing the properties of the COM+ application from the Component Services management console. So, the combination of the application ID and the CLSID (ProgID reference from COM) is a direct pointer that allows the WCF COM+ integration runtime to locate, instantiate, and service the WCF client call.
If you check the properties of the OldHorse.PositionManagement component from within Component Services, you’ll see that the CLSID GUID and application GUID both match the generated GUIDs in the OldHorse.PositionManagement.svc file as shown in the figure below, noting that the 2nd parameter, Application GUID will be different on each machine.
Figure 10-11. OldHorse.PositionManagement properties
Using ComSvcConfig.exe Utility
You can also use the stand-alone ComSvcConfig.exe utility to generate the required resources COM+ application integration. The primary difference is it doesn’t provide the up-front validation that the SvcConfigEditor.exe utility does for validating supported COM interfaces prior to generation. Instead, it provides that information as error messages at runtime.
Using the same COM+ application as an example, the following command generates the required resources for wrapping your COM+ application’s PositionManagement interface in a WCF service and hosting inside IIS/WAS (all on a single line).
ComSvcConfig.exe /install /application:OldHorse /contract:OldHorse.PositionManagement,_PositionManagement /hosting:was /webdirectory:VB6ComSample /mex
In addition to the /install option listed here, there are two additional primary actions: /list and /uninstall. The /list option enumerates what WCF COM+ integration services currently exist on the local machine. The /uninstall option removes the application .svc file in addition to updating the Web.config (or application configuration) file, removing all references to the identified application and interface.
Client Proxy Generation
At this point, you’re ready to create the client proxy for your WCF COM+ integration, using either the SvcUtil.exe utility or the Visual Studio 2005 Add Service Reference add-in, as described in Chapter 5 of our book. Before proceeding, ensure that the IIS website that you will be using has anonymous access enabled (accessed through the Directory Security tab in IIS Virtual Directory properties). A completed solution appears in the sample code in \VB6ComClient directory.
In this section, you’ll create a simple console application. Start Visual Studio 2005, and create a new Windows console project. Once you have done this, right-click the project (or select the Project menu), and choose Add Service Reference. You can find detailed steps for generating service proxies in Chapter 4 of our book. The URI to specify for the Add Service Reference dialog box looks like Figure 10-12.
Figure 10-12. Adding a service reference to a COM+ WCF wrapper
Once you’ve generated the service reference, you can now provide the client code. Inside the Main method, the example code looks like Listing 10-4, which shows the completed client project’s program.cs class file.
Listing 10-4. WCF COM+ Integration Client
static void Main ( string args )
OldHorse._PositionManagementClient proxy =