Migrating ASP Applictions to ASP.NET...

If you haven't the time or resources to convert or re-write legacy code to the new platform you can can make use of .NET's interoperability features to re-use this legacy code until such time as the resources are available.


By: Chris Sully Date: July 29, 2003

Introduction

.NET is a distinct improvement on the old way of developing Microsoft applications and any new application should ideally be developed in .NET. However, if you haven't the time or resources to convert or re-write legacy code to the new platform you can make use of .NET's interoperability features to re-use this legacy code until such time as the resources are available or the application naturally reaches the end of its useful life.

Several types of code can be re-used:

These are exactly the areas we shall consider in this overview article.

Running ASP and ASP.NET Together

You can continue to run existing ASP pages on your .NET servers, convert the pages to the new technology or move COM components to ASP.NET from ASP pages.

One of the major problems you need to be aware of with having ASP and ASP.NET pages running side by side in the same application is the inability to share state information between the two. This problem in most cases means that realistically you are going to want to convert you existing pages over to ASP.NET / VB.NET and here is a partial list of some issues you may want to consider when you undertake this task:

Late Binding

ASP.NET supports nearly all the syntax and objects that ASP supported. In particular, the Server.CreateObject method for creating late-bound COM components is still supported. You may recall that a common use for Server.CreateObject was for connecting to databases via ADO.

However, not all COM components can be instantiated in ASP.NET in this way due to legacy threading restrictions. In particular, components that use the Single Threaded Apartment (STA) threading model will not function properly in ASP.NET unless you add a compatibility directive to the page:

<%@Page aspcompat="true"%>

As a consequence you often can simply leave the code almost exactly the same but with the addition of adding this directive to your page. However, this should be considered a short term fix only as you are likely to be limiting the potential performance of your application in this way not making use of the improvements in ASP.NET. You are basically limiting the number of users who can access the page / component simultaneously.

ActiveX Controls

ActiveX controls became an important means of delivering encapsulated functionality with a user interface (UI) component to both windows and web applications. ActiveX controls have a standard set of interfaces through which they communicate with the hosting container, e.g. a web page / web browser. Thus by supporting these interfaces, an application can make use of an ActiveX control, without requiring any knowledge of the internal workings of the control.

Initially ActiveX controls were mainly aimed at Windows applications but Microsoft brought them to the web by making Internet Explorer (IE) an ActiveX container. However, in the .NET world ActiveX controls have been replaced by server-side controls derived from the system.web.ui.control class. Whereas .NET controls are executed on the server, emitting HTML to the client, ActiveX controls are entirely client side, being instantiated on the client. Hence it's still up to the browser to handle the ActiveX control.

The functionality offered by ActiveX controls is gradually being replaced by .NET controls or other .NET alternatives where a particularly rich UI is required, but you can actually add ActiveX controls to the web forms toolbox in VS.NET and thus can then add them easily to web forms though the support that VS.NET provides for actually using the controls is minimal. To add an ActiveX control to the toolbox right click the toolbox and select customise toolbox. Select the COM components tab in the dialog box and scroll down to the ActiveX control you wish to add.

A few considerations before you use ActiveX controls:

Hence you should consider carefully whether you want to use ActiveX controls. If there is a native .NET alternative this would generally be preferable. Alternatives include .NET server side custom controls or controls distributed via the smart client model – see the .NET SDK for further information. Look out for articles on both on DotNetJohn.

Using COM components

The last considered case of using ActiveX controls on web forms is a special case of a more general problem – using legacy COM code from a .NET application. As opposed to ActiveX components you can, of course, run COM components on the server as well. There is a great deal of legacy COM code out there and a gradual migration is sensible for several reasons:

We'll take a look at how you can encapsulate COM components from a .NET application shortly but first we'll have a quick review of the closely related subject of wrapper classes.

We know that VB.NET creates managed code that operates within the .NET CLR with the various benefits this offers. Code, e.g. COM components, that operates without the CLR is unmanaged code without this inherent support. To allow interoperability between managed and unmanaged code we must use a proxy to facilitate communication between the two. A proxy is an object we can treat as if it was the actual object we want to deal with – it hides the fact that it isn't the actual object while enabling communication with the actual object. The proxy in this situation is called a runtime callable wrapper (RCW) – a proxy that can be called by the CLR.

Fortunately COM components, just like .NET components have metadata that describes their interface. For .NET components this information is stored in the assembly manifest; in COM components the metadata is stored in a type library. The .NET framework includes a tool, the Type Library Importer (tlbimp.exe) that can create a RCW using the metadata contained in a type library.

As with ActiveX controls VS.NET also allows easy use of COM components in your .NET code. This achieved via using the COM option of the Add Reference dialog box. This has a similar effect to using tlbimp.exe, though with a few restrictions we shall mention shortly. VS.Net creates a new namespace with the name of the original library and then exposes the classes from the library within that namespace.

Which method should you use? Direct reference as used by VS.NET is only suitable for a truly private component that does not need to be shared. The type Library Importer tool should be employed for components that need to be shared as you can sign the resultant assembly and place it in the Global Assembly Cache. Further if you need to control the details of the created assembly such as its name, namespace or version number you must use the type library importer. The direct reference method gives you no control over these details.

Using COM+ components

COM+ is the component services layer of Windows 2000 and later operating systems, supplying a number of services:

Look out for a further DotNetJohn article on the subject of COM+ in .NET but for the purposes of this article all you need to know is that very little is different between using COM+ and COM components.

Using Platform Invoke

Another way .NET can interact with unmanaged code is via functional calls to unmanaged libraries such as the Windows API. This is achieved via platform invoke.

The Declare statement tells the CLR where to find an API function by specifying the name of the library and the name of the function. Once the function has been declared in this way it can be used just like any other function in .NET. An example:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.Text" %>
<script runat="server">

    Declare Auto Function GetComputerName Lib "kernel32" (ByVal lpBuffer as string, ByRef nSize as integer) as integer

    Sub Page_Load()
      Dim strBuf as String = New String(CChar(" "), 128)
      Dim intLen as integer = strBuf.length
      Dim intRet as integer = GetComputerName(strBuf, intLen)
      lblComputerName.text= "This computer is named " & strBuf.ToString.Substring(0,intLen)
    End Sub
</script>
<html>
<head>
</head>
<body>
    <asp:Label id="lblComputerName" runat="server"/>
</body>
</html>

The web form will display the name of the computer where the code is run. The Declare statement tells the CLR where to find an API function by specifying the name of the library (here kernel32) and the name of the function (here GetComputerName). Once declared your code can use the function. The Auto modifier instructs the .NET Framework to use the appropriate version of the API call for the platform where the code is running, either the ANSI or Unicode versions.

Conclusion

I hope this article has proved an informative overview of some of the issues involved in migrating your existing ASP applications to ASP.NET. You may also be interested in related series of articles concerned with utilising Component Services (COM+) with .NET, coming shortly to DotNetJohn.

References

Developing and implementing web applications with VB.Net and VS.Net
Mike Gunderloy
Que

.NET SDK documentation