Introduction
When migrating from an existing ASP 3.0 application to ASP.NET, a number of factors can complicate the situation. These may include how to make use of existing COM objects for the middle layer, how to restructure existing UI code as user controls, etc. Sometimes, a full transition to ASP.NET is not possible in one fell swoop. Instead, the existing ASP application may be required to live along side of the new ASP.NET application for quite some time while the site is ported on a phase-by-phase basis.
If you don't care about a fictitious business-case scenario, feel free to jump right to the code in "Solution Alternatives".
Case Study: International Staffing Company's Web Based Career Services Center
The fictitious company International Staffing Company (ICS) has an existing ASP 3.0 application. It is comprised of a backend database of Oracle, a middle tier of COM Objects, and front-end written in ASP with VBScript on the server and JavaScript for the web browser. Their site template consists of a left side menu, header section, and footer section. The appearance of these areas is constructed through complicated logic that examines the roles and responsibilities of the logged in user to determine which parts are accessible and appropriate for rendering.
ICS has decided to implement some new features of their web site using ASP.NET because they don't want to fall behind the times and lose their programmers to other companies. But, ICS expects that after the new development, only 5% of the application's UI will be done in ASP.NET, while the rest of the application will remain ASP.
ICS hardly sees the justification of rewriting their entire application using ASP.NET just to implement 5% of the application. As a result, ICS would like to make use of as much existing code for the time being and do as little refactoring as possible until the time is ready.
Problem Statement
How can we migrate existing UI rendering logic from our ASP application to an ASP.NET application? And, how can we do it such that the two applications can live side by side and that changes made to the ASP application's UI rendering logic are inherited by the ASP.NET application?
Complicating Factors
Here are some complicating factors:
- ICS has chosen to use as a base for their new efforts a freely available portal system upon which they can build new parts or modify existing parts. This will eliminate the need to build all the needed code from the ground up.
- The portal system must live in its own virtual directory.
- As mentioned above, there are thousands of different users for this application, and based upon their roles, the user interface changes for each login.
- Changes to the ASP 3.0 application are expected to continue concurrently.
Solution Alternatives
Some ideas come to mind in this situation:
- Rewrite the application UI logic so that it is done as Custom User Control in ASP.NET.
- Use the
System.Net.WebClient
class to call the existing application to extract the user interface code and place it into the HTTP response.
- Store the HTML code for the interface into a JavaScript and use the
document.write
method in the browser to construct the page GUI at render time.
Problems With 1 and 2
Options 1 and 2 sound attractive at first glance, but they suffer from a couple of fatal pitfalls:
In option 1, ICS has made it clear that they do not want to redesign everything right now as it would take too much time and they do not want to maintain two code bases while changes continue to happen in the ASP 3.0 application.
In option 2, the flaw is that since the user interface changes for each user logged in, the WebClient
class, which executes on the server, would have to mimic the logged in user. While this is possible, it may not be possible in all situations, such as when digital certificates are required for authentication for log in.
Solution Chosen: Use JavaScript to Write out the HTML
Option 3 is the most pragmatic and easiest approach. Here's why:
- The user must authenticate through the existing ASP application before any of the ASP.NET content can be accessed.
- Modifying the ASP application to send chunks of HTML embedded into JavaScript scripts is very easy to do.
- Future changes to the ASP application's interface will automatically be inherited by the ASP.NET application.
Solution Outline
The solution will have three parts:
- A header portion of the existing ASP application that contains functions that will render all three template areas as discrete chunks of HTML.
- A page area of the existing ASP application that uses the functions to render these three chunks as JavaScript variables.
- An ASP.NET page that includes a reference to the ASP page in a JavaScript
SCRIPT
tag and then writes these chunks to the client page during render time.
Code for Original ASP Page
<%
Dim userRole
userRole = "PUBLIC"
If Len(Request.QueryString("userRole")) > 0 Then
userRole = Request.QueryString("userRole")
End If
Dim strMenuLeft, strMenuTop, strMenuBottom
Dim scriptUrl
scriptUrl = Request.ServerVariables("SCRIPT_NAME") & "?userRole=" & userRole
strMenuLeft = _
"<div id='pnlMenu'>" & vblf & _
" <b>User Role:" & userRole & "</b>" & vblf & _
" <div class='mnuOptions'>" & vblf & _
" <div class='mnuTitle'>View</div>" & vblf & _
" <div class='mnuItem'><a href='" & scriptUrl & _
"&cmd=ViewServices'>Services</a></div>" & vblf & _
" <div class='mnuItem'><a href='" & scriptUrl & _
"&cmd=ViewProducts'>Products</a></div>" & vblf & _
" </div>" & vblf
If userRole = "EDITOR" Or userRole = "STAFF" Then
strMenuLeft = strMenuLeft & _
" <div class='mnuOptions'>" & vblf & _
" <div class='mnuTitle'>Edit</div>" & vblf & _
" <div class='mnuItem'><a href='" & scriptUrl & _
"&cmd=ModifyServices'>Modify Services</a></div>" & vblf & _
" <div class='mnuItem'><a href='" & scriptUrl & _
"&cmd=ModifyProducts'>Modify Products</a></div>" & vblf & _
" </div>" & vblf
End If
If userRole = "STAFF" Then
strMenuLeft = strMenuLeft & _
" <div class='mnuOptions'>" & vblf & _
" <div class='mnuTitle'>Manage</div>" & vblf & _
" <div class='mnuItem'><a href='" & scriptUrl & _
"&cmd=ManageUsers'>Manage Users</a></div>" & vblf & _
" <div class='mnuItem'><a href='" & scriptUrl & _
"&cmd=ManageSite'>Manage Site</a></div>" & vblf & _
" </div>" & vblf
End If
strMenuLeft = strMenuLeft & "</div>"
strMenuTop = "Home | Products | Services | Search | Feedback"
strMenuBottom = "Home | Privacy | Copyright"
%>
<html>
<head>
<title>International Staffing Company</title>
<link rel="stylesheet" type="text/css" href="style.css"></link>
</head>
<body>
<img src="images/isclogo.gif"><br />
<table border="0" cellpadding="2" cellspacing="6">
<tr valign="top">
<td><%=strMenuLeft%></td>
<td>
<table border="0" cellpadding="0" cellspacing="0>
<tr valign="top">
<td><%=strMenuTop%></td>
</tr>
<tr valign="top">
<td><br /><br /><br />[Content Area]
<br /><br /><br /></td>
</tr>
<tr valign="bottom">
<td><%=strMenuBottom%></td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
Code to add to Original ASP Page VBScript to Render Values as JavaScript
strMenuTop = "Home | Products | Services | Search | Feedback"
strMenuBottom = "Home | Privacy | Copyright"
Dim renderType
renderType = Request.QueryString("renderType")
If renderType = "js" Then
Response.Write PackageAsJS(strMenuLeft, "strMenuLeft") & vblf
Response.Write PackageAsJS(strMenuTop, "strMenuTop") & vblf
Response.Write PackageAsJS(strMenuBottom, "strMenuBottom") & vblf
Response.End
End If
Function PackageAsJS(str, name)
str = Replace(str, vblf, "\n")
str = Replace(str, """", "\""")
str = Replace(str, vbtab, "\t")
PackageAsJs = name + " = """ + str + """;"
End Function
Code for ASP.NET Page that Reuses the ASP Content
<html>
<head>
<title>International Staffing Company</title>
<link rel="stylesheet" type="text/css" href="style.css"></link>
<script type="text/javascript" src=
"http://localhost/ASPapp/Menu.asp?userRole=STAFF&cmd=ViewProducts&renderType=js">
</script>
</head>
<body>
<img src="images/isclogo.gif"><br />
<table border="0" cellpadding="2" cellspacing="6">
<tr valign="top">
<td>
<script type="text/javascript">
<!--
document.write(strMenuLeft);
//-->
</script>
</td>
<td>
<table border="0" cellpadding="0" cellspacing="0>
<tr valign="top">
<td>
<script type="text/javascript">
<!--
document.write(strMenuTop);
//-->
</script>
</td>
</tr>
<tr valign="top">
<td><br /><br /><br />
<form runat="server">
<input type="text" runat="server"
value="[Content Area]" />
</form><br /><br /><br /></td>
</tr>
<tr valign="bottom">
<td>
<script type="text/javascript">
<!--
document.write(strMenuBottom);
//-->
</script>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
How it Works
The code at the top of the .asp page checks the user's role and then renders the menu items as appropriate for that user. Later on, those dynamic values are written to the client. The new code is used to intercept the "renderType" parameter, and if it equals "js", then the HTML is escaped as JavaScript strings for the .NET client to apply to the client during render time. Of course, the link is hard-coded, but the idea is illustrated.
Summary
While it is nice to start projects fresh with the latest and greatest technology, sometimes this is not possible due to time constraints or current investment. Instead, a phased approach can mitigate concerns of technical obsolescence, while ushering in new functionality in a way that preserves the end-user experience. I hope you found this simple technique useful.