Using Automation (ActiveX/COM) Objects in ASP.NET
By Peter van Ooijen
Published: 4/26/2002
Reader Level: Intermediate
Rated: 3.50 by 2 member(s).
Tell a Friend
Rate this Article
Printable Version
Discuss in the Forums

Sometimes we are tempted to believe that .NET is a cure for all of our development problems and that every technique used in the pre .NET days should be sent to the recycle bin this moment. A technique which suffers greatly from this misunderstanding is ActiveX, also known as (OLE) automation or COM. The CreateObject function creates COM objects and is often used in classical ASP server side scripts to customize Web pages. It has not always led to the best coding practices, but it worked. The ASP.NET server side controls and the truly object oriented .NET Framework are a huge step forward. A lot of problems COM used to solve are now better in .NET, but that does not mean that COM no longer exists. Some of your existing COM classes work very well, why should you convert them to .NET? That's not what COM promised you! Relax, there are still a lot of things you can do with COM in ASP.NET. In this article I will show you some of the great COM support it has to offer.

COM's Not Dead!

Before we dive into the .NET support I want to take a closer look at COM itself. COM stands for the Component Object Model which describes a protocol to separate the interface of an object from its implementation. The interface is what the object looks like, it is the declaration of the properties and methods. The implementation is the code which actually runs when a method is called or a property is read. The user of an object uses COM to get a description of the class and a way to construct an object of the class. The user will get a COM interface to the object. All methods and properties can be executed on this interface, but the COM object cannot be destroyed by the user The COM object will be kind of garbage collected. All of this is not uncommon, interfaces are widely supported in .NET. Describing classes is something .NET is very good at and every assembly has its metadata. COM uses typelibraries to describe classes, they are quite often available as a resource inside the library file itself.

Windows supports a variety of COM-interface types, the most commonly used is the Idispatch interface. A COM class implementing this interface exposes its functionality in two ways:

  1. Its methods can be called directly from the vtable of the object, the layout of this vtable is described in the typelibrary of the COM class. A compiler will map calls to the vtable. This is called vtable binding, these days it is called early binding as well. (Actually early binding refers to dispinterfaces, whose scope is limited to COM events).
  2. The interface has methods which accept the name of the method or property in string format, perform a run-time lookup in the typelibrary after which the method can be invoked. A script interpreter will use these methods to map script calls to object methods. This is called late binding.

Classical ASP scripts use the second technique to populate Web pages on the server. Client side scripts use late binding to run code in the browser on the client. Objects which are addressed using these Idispatch interfaces are often called (OLE) automation objects. The term ActiveX was once coined for all COM functionality but these days it is mainly used to describe visual (ActiveX-) controls which are addressed using a whole bunch of different COM interfaces.

COM is a great protocol for connecting software components created with different tools, it is supported by all major Windows languages like VB(A), Delphi, C++, VBscript and JavaScript and last but not least .NET. In the .NET Framework class libraries you will find the System.runtime.interop namespace. The majority of the methods and properties in there deal with Unmanaged COM interoperability which involves the creation of COM objects as well as passing data to and from these objects. COM objects do not operate in the type safe .NET managed environment. Communication between the managed and the unmanaged world is quite a job. The passing of data is known as marshalling, .NET will use the system marshaller of .NET itself to implement the marshalling of COM objects. Sometimes you hear people say that parts of the kernel of .NET are implemented using COM. I would say that COM and .NET use the same techniques to get objects connected.

Let's start working with COM in an ASP.NET application. I have built a very simple automation server. It is named DemoServer.MyDemo and has one method, named MyMethod, taking one string type parameter and returning this string prefixed with "your server echoes ". It was built using Delphi, for more information how to do this you are invited to www.Gekko-Software.nl/Software.htm.

A Client Side Automation Object

In an ASP.NET application all code runs on the (IIS-) server. Code running on the client can do very specific things like inspecting a specific hardware device or the surfer's address book and report to the server part of the application. When implemented as an automation server, its objects can be created and manipulated by just a small piece of script on the page being browsed. Because I am not very good with html, I prefer to implement all this in C# code-behind on a Web page.

I will experiment with a simple Web page. This page has two TextBoxes and a Button. These controls are all server side controls which means that they are not available on the client in the same way as they are on the server. The TextBoxes will have a client control representation in the form of text input controls. My script can read and set their text values and the server will see these in the postback. The first TextBox is used to enter a string which will be passed to the automation object, the second TextBox will hold the result of a function call on the object. I will write a Jscript function which will create the automation object, read the TextBox, call a method and update the second TextBox.

function doMySubMit() {
  var MyAx;
  MyAx = new ActiveXObject("DemoServer.MyDemo");
  document.getElementById('TextBox2').value = MyAx.MyMethod(document.getElementById('TextBox1').value);
}

ActiveXobject is the Jscript function which creates a new automation (ActiveX) object as identified by the ProgId parameter. On the resulting object I fire MyMethod passing it the string in TextBox1. The result is written to TextBox2.

In C# constants have to be stored in classes, just like everything else. I will create a static class to hold the script source and the related constants:

class MyJScript {
const string head = "<script language=\"JavaScript\">";
const string foot = "</script>";
public const string scriptBlockName = "startup";
public const string functionName = "doMySubMit()";
public const string MySubmit =
                           head +
                           "function " + functionName + "{" +
                           "var MyAx;" +
                           "MyAx = new ActiveXObject(\"DemoServer.MyDemo\");" +
                           "document.getElementById('TextBox2').value = MyAx.MyMethod(document.getElementById('TextBox1').value);" +
                           "}" +
                           foot;
                           }

A static class can be used without creating an object instance. After declaration I can use MyJscript.MySubmit, a constant which contains the JavaScript source wrapped up in script tags.

In the Page_Load event I have the opportunity to tailor the page to my needs. Besides setting the controls I can inject client side script here. Page.RegisterStartupScript injects a a script block in the page. Before doing so, Page.IsStartupScriptRegistered will check if the scriptblock had already been added to the page to prevent double work. Page.RegisterOnSubmitStatement is an even more powerful method, here I can define the name of a client-side script function (from my freshly inserted script block) which will fire when the form is submitted to the server. The MyJScript class provides all parameters needed for these methods.

private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
if (! IsStartupScriptRegistered(MyJScript.scriptBlockName))
  RegisterStartupScript(MyJScript.scriptBlockName, MyJScript.MySubmit);
RegisterOnSubmitStatement("Mysubmit", MyJScript.functionName);
}

When the page is submitted my Jscript function will run on the client and its result can be checked by inspecting the submitted TextBox2. Internet Explorer will notice that there is something potentially very dangerous going on. The automation object could house any code which could redistribute the client's address book or even format its disks. When its security settings are not set too low, IE will pop up a warning dialog.

To prevent this dialog from appearing you could either change the safety setting or sign your ActiveX class. The first option should not be taken too serious. For the second one you will end up with a company like Verisign to buy a certificate with which you can sign your automation class as being trustworthy. Signing is a snap in .NET, but for classical automation classes it takes more time and money.

A Server Side Automation Object

In classical ASP most scripts run on the server. Automation objects used in these scripts are useful to pass (part of) the work to a software component which is built with a better suited and more reliable tool. In scripts everything is late bound, a lot of errors will not be noticed until the script is actually executed. Besides that compiled code does run faster than interpreted code. With ASP.NET this "scripting hell" can be sent to the recycle bin and a lot of the automation objects which just generated html code can be discarded as well. Then all that remains are the automation classes which still do something useful. One option is to rebuild them in .NET and the other is to use them as they are. The marvelous support for automation in .NET makes the latter a snap.

In the solution explorer I will add a reference to the COM library I want to use. After clicking "Add Reference" in the solution explorer I pick the COM tab and select the DemoServer library. Now Visual Studio will import the typelibrary and generate a wrapper class for the DemoServer automation class. My project now has a namespace interop.DemoServer which houses MyDemoClass which implements the ImyDemo interface which has a method MyMethod.

I can use the automation class like any other .NET class. Clicking Button2 creates the automation object and calls its method.

private void Button2_Click(object sender, System.EventArgs e)
{
  DemoServer.MyDemoClass axo = new DemoServer.MyDemoClass();
  Label1.Text = axo.MyMethod(TextBox1.Text);
}

That's all. All code runs, early bound, on the server in the code-behind of the Web page. I have all server-side stuff available, including the server-side version of the controls, I no longer need a TextBox to assign the result to, a label will do.

In ASP.NET you can keep using your automation objects thanks to .NET Interop which makes the using of automation objects inside .NET code seamless. Running an object on the client is actually just the same as in pre-ASP.NET days. The client is not aware that it is running .NET, it just runs a script. ASP.NET provides very nice functionality to install client side scripts.



Marketplace
(Sponsored Links)
What are the green links?
   



 
Copyright © 2007 CMP Tech LLC |
Privacy Policy (4/10/06) | Your California Privacy Rights (4/10/06) | Terms of Service | Advertising Info | About Us | Help