COM Interoperability in the .NET FrameworkBy Prashant Tailor
COM stands for Component Object Model, which is binary specification for software code re-use. It imposes a standard for the interfaces through which client code talks to component classes. Since classic ASP was limited in its functionality, in order to perform certain tasks in an ASP Web application, a COM component was needed. For example, creating images, examining the Event Log, or performing a remote HTTP request were all tasks that required a COM component.
COM components were commonly used to encapsulate business logic, as discussed in
Using Business Objects in your ASP Web Application.
An eCommerce Web site might create
a COM component that had methods like
CalculateArrivalDate(shipToZipCode), which would compute the shipping costs for
the items in a particular user's shopping cart and calculate how long it would take a shipment to
reach the buyer. The advantage to placing such business rules and logic in COM components includes
improved code readability and maintainability.
Since ASP.NET Web pages have access to the classes in the .NET Framework, ASP.NET Web pages can, without components, perform tasks like creating images, examining the Event Log, or performing a remote HTTP requests. However, it is still a wise idea to encapsulate business logic into components, as discussed in the article Displaying Custom Classes in a DataGrid.
The components used by an ASP.NET Web page are commonly referred to as .NET components, and differ from COM components in a number of important ways. These differences mean that your ASP.NET Web pages cannot natively use COM components. Rather, some sidestepping must be done to allow for interoperability between classic COM components and an ASP.NET Web page. In this article we are going to look at the concepts and walk-through an example that demonstrates COM interoperability in the .NET Framework.
COM components have different internal architecture from .NET components, hence they are not innately compatible. Most organizations, which have built their enterprise applications on COM objects for their middle tier services, cannot write off the investments on these solutions. That is, for such companies to migrate to ASP.NET there needs to be a way for the new ASP.NET Web pages to use the old, legacy COM components.
In order to have a COM component used through an ASP.NET Web page, we will be using what is called a Runtime Callable Wrapper (RCW). The RCW translates specific calls from the ASP.NET Web page into COM-specific invocation requests on a COM component. When using RCWs, our ASP.NET Web page will believe that it's talking to just another .NET component instead of talking to a COM component.
The following graphic depicts the RCWs role. On the left is the .NET Application (you can think of this as our ASP.NET Web page). On the right is the legacy COM component that we want our ASP.NET Web page to work with. In the middle sits the RCW, which accepts incoming requests from the ASP.NET Web page, translates them so that they can be handled by the COM component, and then passes them onto the COM component. Essentially, the RCW acts as managed proxy to the unmanaged COM component.
When we make a method call, it goes onto RCW and not the object itself. RCW manages the lifetime management of the COM component.
Creating the Runtime Callable Wrapper
There are two ways to create the runtime callable wrapper:
- Through the Visual Studio .NET IDE
- Using Type Library Importer utility (executed via the commandline using
tblimp.exe) - you must use this approach if you do not have Visual Studio .NET installed
InteropExampleRCW.dllfrom a legacy COM component named
InteropExample.dll, the following syntax can be used from the Windows command prompt:
tlbimp InteropExample.dll /output:InteropExampleRCW.dll /verbose
(If you'd like, you can view a screenshot of
tlbimp.exe in use.)
The Type Library Importer interrogates the COM DLL's type library and translates the information therein into .NET format. The metadata assembly generated contains wrapper classes that can be used any .NET client - an ASP.NET Web page, a C# windows clients, and so on. The RCW is created on the fly whenever component is created and acts like managed types to COM specific data types.
In addition to being able to create a RCW through the commandline, we can also create an RCW via Visual Studio .NET. In order to accomplish this, click on Project / Add Reference / COM Tab, which will show a dialog box similar to the one below. The tab lists registered components on the local machine. Simply select the desired COM DLL and add it to list of selected components. Once you click OK, VS.NET will automatically generate metadata assembly and place the classes provided by that component into a namespace with the same name as COM DLL.
Examining the Structure of Wrapper Assembly
In order to understand how to use the RCW it is important that we know the structure of the wrapper assembly (the wrapper assembly is the DLL file created by
tlbimp.exeor the VS.NET IDE). To examine the wrapper assembly, you can use Microsoft's .NET disassembler,
ildasm.exe, in the following manner from the command prompt:
In the download section at the end of this article I have created a simple example VB 6.0 COM component
that has two classes:
Titles. When creating the RCW, a new assembly
will be generated, which has the following two classes:
AuthorsClassclass contains the same methods and properties that the COM component's
Authorsclass contains. That is, the
AuthorsClasshas the method
TitlesClasshas the method
GetTitles(), which are the methods found in the original COM component. (You can view a screenshot of ILDASM in action.)
Using the Legacy COM Component in an ASP.NET Web Page via the RCW
If you are using Visual Studio .NET, the first step is to add the new .NET component (the RCW) to your project. You can do this by going to Project / Add Reference / .NET tab, and choosing the RCW you created for the legacy COM component that you want to use. If you are not using VS.NET, then you will manually need to copy the RCW assembly (the DLL file) into your Web application's
From here, you can just use the appropriate RCW class as an interface into the legacy COM component.
For example, the following source code comes from the source code included at the end of this article,
and creates an instance of the RCW's
AuthorsClass and calls its
method. This method accepts a string parameter and returns an ADODB Recordset containing authors
that match the string query:
The above code uses the
ADODB.Recordset object, since the legacy COM component's
GetAuthors() method returns an ADODB Recordset object. In order to use this code
you will need to include a reference to the Microsoft ActiveX Data Objects 2.7 Library, which
can be accomplished by going to Project / Add Reference / COM tab, and selecting the appropriate
COM object. A future
article of mine will talk about using the ADODB services in an ASP.NET Web page in much greater
The above code starts by creating an instance of the RCW's
Recall that this class serves as a proxy between your ASP.NET Web page and the COM component. That
is, when the RCW's
GetAuthors() method is called, the call ispasssed onto
the COM component, which then runs and returns a value, which is passed through the RCW back up to
your ASP.NET Web page. So, by using the RCW you are using the legacy COM component, calling its methods.
The RCW serves as an intermediary of sorts.
Once an instance of the
AuthorsClass class has been created, an
object is created and assigned the return value of the
GetAuthors() method call. This
ADODB.Recordset is then used to fill a DataSet, which is then bound to a DataGrid.
To summarize, the above code gets an ADODB Recordset back from a legacy COM component, and displays the
resulting Recordset in a DataGrid.
In this article we examined how to use runtime callable wrappers (RCW) to allow for an ASP.NET Web page to call a COM component. Creating the RCW is fairly simple, and can be done either via the commandline or through the Visual Studio .NET IDE. Once the RCW has been created, it needs to only be included in the Web application and then you can start using it in your ASP.NET Web pages. Through this means you can use legacy COM components in your .NET applications!
About the Author
Prashant Tailor is Bachelor of Electronics Engineer, currently working as Microsoft solution developer. He possesses 5 years of IT experience in analysis, design and development of client/server and Web-applications using Visual Basic, C#, ASP, COM/DCOM, SQL Server and Oracle.