
Figure 1. A report of the Internal Computer Services Department's ongoing projects
Examining the Project Report Code
The source code for the entire Project Report application is encompassed within a single ASP page, which uses a postback form to handle the user's report customization options. Because this document focuses on porting an ASP application to ASP.NET, an explanation of how the ASP code works is not included. It is assumed that you have a working knowledge of how ASP and ADO data access are used to build applications today.
The following code shows an ADO Connection object being created and opened to a Microsoft Access database.
Set objConn = Server.CreateObject("ADODB.Connection")
objConn.ConnectionString = _
"PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=" & _
Server.MapPath("Projects.mdb") & ";"
objConn.OpenA recordset is populated with the Name and DepartmentID for each row in the Department table. The contents of this recordset are then displayed in a list box.
Set objDeptListRS = Server.CreateObject("ADODB.Recordset")
objDepartmentListingRS.Open "Department", objConn, _
adOpenForwardOnly, adLockReadOnly, adCmdTable
'Iterate through the Recordset
Response.Write "<b>Department:</b> " & _
"<select size=""1"" name=""lstDepartmentID"">"
Response.Write "<option value=""-1"">" & _
"-- Show All Departments --</option>" & vbCrLf
Do While Not objDeptListRS.EOF
Response.Write "<option value=""" & _
objDepartmentListingRS("DepartmentID") & """"
'Do we need to make the item SELECTED?
If CInt(objDepartmentListingRS("DepartmentID")) = _
CInt(iDepartmentID) then
Response.Write " selected"
End If
Response.Write ">" & objDeptListRS("DepartmentName") &_
"</option>"
objDeptListRS.MoveNext
Loop
Response.Write "</select>" & vbCrLf & vbCrLfNext, a dynamic SQL query is constructed based on the options selected by the user. Note in the following code that the SQL query's WHERE clause is created so that it always retrieves only those projects that began in the previous year. Based upon the user's selections, the WHERE clause is potentially extended further. The variables iDepartmentID and strProjectView are variables defined earlier and assigned to the list box values selected by the user.
strSQL = "SELECT D.DepartmentName, ProjectName, " & _
"StartDate, EstimatedEndDate, ActualEndDate, " & _
"Priority, ProjectDescription " & _
"FROM Project P " & _
"INNER JOIN Department D ON " & _
"D.DepartmentID = P.DepartmentID " & _
"WHERE StartDate >= #" & _
DateAdd("yyyy", -1, Date()) & "# "
'Now, construct addition WHERE clauses if needed
If CInt(iDepartmentID) <> -1 then
'Add a clause for the department ID
strSQL = strSQL & " AND P.DepartmentID = " & _
iDepartmentID
End If
'What types of projects do we want to view?
Select Case strProjectView
Case "ongoing":
strSQL = strSQL & " AND ActualEndDate IS NULL"
Case "completed":
strSQL = strSQL & " AND ActualEndDate IS NOT NULL"
End SelectAnother Recordset object, objProjectsRS, is created and populated with the results of the above dynamic SQL query. Finally, this recordset is iterated through and displayed as an HTML table.
'Output the HTML table tag and th tags
Response.Write "<p><table align=""center"" " & _
"border=""1"" cellspacing=""1"">" & vbCrLf
Response.Write "<tr><th>Project</th><th>StartDate</th>" &_
"<th>Estimated Completion</th><th>Actual " & _
"Completion</th><th>Priority</th>" & _
"<th>Description</th></tr>" & vbCrLf
'Loop through the entire Recordset
Do While Not objProjectsRS.EOF
'Display the Recordset information
objProjectsRS.MoveNext 'move to the next record
Loop
Response.Write "</table>" & vbCrLf & vbCrLfPorting the ASP Application to ASP.NET
When porting an ASP application to ASP.NET, you will need to decide how much time you want to spend incorporating the new features of ASP.NET into the existing ASP application. Changing an ASP page's file extension from .asp to .aspx and correcting for some syntactical changes is usually enough to get an ASP page working as an ASP.NET page. Such a port, although it can be completed quickly, does not take advantage of many of the new features of .NET, including ASP.NET Web controls, Microsoft ADO.NET, the Microsoft .NET Framework classes, etc. Although a more complete port may take more time, your finished ASP.NET pages will be readable and maintainable, and more feature-rich.
As a developer, you need to weigh the tradeoffs when deciding what approach to take when moving an ASP application to ASP.NET. If you are pressed for time, a simple port from ASP to ASP.NET may be in order; if no such deadline looms, it may be worthwhile to take the time to build a rich ASP.NET application from the ground up. You can also, of course, take an incremental approach. If you ran a large site that utilized a number of COM components to implement business rules, you may decide to port over just the UI portion of your Web application, and continue to use the classic COM components.
In this next section, you will examine porting the existing ASP code to ASP.NET, making as few modifications as possible.
Porting ASP Applications to ASP.NET
To port an existing ASP application to ASP.NET, the first step is to rename the file extension of the ASP pages from .asp to .aspx. Because the Project Report Application has a single ASP page, this renaming task is simple enough. Once you've made this change, take a moment to visit the new .aspx page through your Web browser. Did it load without error? Most likely not; chances are your VBScript code contains some syntactical problems.
When porting the ASP application we examined earlier, the first error message you will receive is an error concerning Option Explicit, as shown in Figure 2.

Figure 2. Option Explicit statement error message
This statement, for an ASP.NET Web page, should be moved to the @Page directive. At this point, edit the .aspx file by removing lines 1 and 2 and replacing them with the following @Page directive:
<% @Page Language="VB" Explicit="True" %>Once this change is made, reload the page in the browser. You will receive another error concerning the lack of parenthesis around the Response.Write statements.

Figure 3. Response.Write statement error message
This generates an error since Visual Basic .NET requires that all argument lists to both subroutines and functions be encased in parenthesis. Check through the entire document and place parenthesis around the argument lists for all of the Response.Write statements, and then reload the ASP.NET page in your browser once again.
Another change from Visual Basic 6.0/VBScript to Visual Basic .NET is that Visual Basic .NET does not support default properties. Default properties allowed developers a bit of a shortcut¡ªif, when using classic COM components in Visual Basic 6.0/VBScript, a developer failed to specify a property, the default property is used. For example, the default property of the ADO Recordset is the Fields collection, and the default property of a Fields collection is the Value property. Hence, when you use:
Response.Write objRecordset("columnName")in classic ASP you are saying, in essence:
Response.Write objRecordset.Fields("columnName").ValueWhen porting your classic ASP pages to ASP.NET, you may receive the following cryptic error message:
Cast from __ComObject to String is not valid.

Figure 4. ASP.NET porting error message
Such an error occurs because Visual Basic .NET does not support default properties, when we use:
Response.Write(objRecordset("columnName"))Visual Basic .NET is trying to cast the Fields object to a String, which it cannot do. Rather, we must indicate that we want to output the Value property by explicitly stating which properties we wish to output:
Response.Write(objRecordset.Fields("columnName").Value)As you continue to port your ASP.NET application you will, invariably, come across other syntactical errors. Table 1 summarizes the syntactical errors encountered when porting the Project Report Application from ASP to ASP.NET.
Note Visual Basic has matured as a programming language with the release of Visual Basic .NET. It now supports try¡catch error handling, true object-oriented development, and many other enhancements that were long overdue. To modernize Visual Basic, though, it was necessary to make some syntactical changes to the language. Therefore, Visual Basic .NET is not 100% backwards compatible with VBScript or Visual Basic 6. 0. For a detailed discussion on the changes in Visual Basic .NET, be sure to read Preparing your Visual Basic 6.0 Applications for the Upgrade to Visual Basic .NET.
Table 1. Syntactical errors encountered when porting the Project Report Application
| Error | Reason | Resolution |
|---|---|---|
| Option Explicit statement not valid inside a procedure. | Option Explicit needs to be defined in the Page Directive using the Explicit attribute. | Add <% @Page Explicit="True" %> to the top of the ASP.NET page. |
| There can only be one Page Directive. | When we added a Page Directive, the @LANGUAGE = "VBSCRIPT" directive in our ASP page became redundant. | Remove the line containing <%@ LANGUAGE = "VBSCRIPT" %> and add the Language="VB" attribute to the Page Directive. |
| Argument lists in call statements must now be enclosed in parenthesis. | Visual Basic .NET requires all subroutine calls to enclose their parameters in parenthesis. A number of Response.Write statements do not contain such parenthesis. | Add the needed parenthesis: e.g., change Response.Write str to Response.Write(str). |
| Let and Set statements are no longer supported on assignment statements. | Because Visual Basic .NET no longer supports default properties, the Let and Set keywords have been removed from the Visual Basic language. | Remove any Let or Set keywords. (In the Project Report Application, the Set keyword assigns Connection and Recordset objects to variables.) |
| Date is a type, and so is not a valid expression. A variable, constant, or procedure is expected. | In the Project Report Application the Date() function was used to get the current date. This is no longer supported. | Replace Date() with DateTime.Now |
| The name IsNull is not declared. | Visual Basic .NET no longer supports the IsNull function. (Recall that in the Project Report Application, a project is not completed if the actual completion date is NULL; in the ASP version IsNull is used to check whether or not the field was NULL.) | To fix, replace IsNull with IsDBNull. |
| Cast from __ComObject to String is not valid. | Visual Basic .NET no longer supports default properties, so when using classic COM components, be certain to explicitly fully state the properties you wish to use. | Change instance of objRS("colName") to objRS.Fields("colName").Value |
COM Component Threading Concerns
Some issues can arise when using COM components within an ASP.NET page, specifically those COM components that have been marked as apartment-threaded or COM objects that access the ASP-intrinsic objects (Request, Response, Server, Application, and Session) through the ObjectContext object.
For example, by default, the ADO objects are marked in the registry as apartment-threaded; when trying to use an apartment-threaded component through an ASP.NET page, you will receive an error instructing you that the apartment-threaded component you attempted to create could not be created. Figure 5 shows the ASP.NET port of the Project Report Application. Note that this error is present because the ADO objects are, by default, marked as apartment-threaded.

Figure 5. An error occurs when attempting to access an apartment-threaded COM component through an ASP.NET page
Fortunately, ASP.NET offers an ASP Compatibility mode, as the error message says. To turn on the ASP Compatibility mode, add the aspcompat=true attribute to the Page Directive. Adding this attribute accomplishes two things:
- ASP.NET uses Single-Threaded Apartment (STA) threads when accessing the COM component. The default is to use Multi-Threaded Apartment, or MTA, threading.
- ASP.NET provides access to the ASP-intrinsic objects in a backward-compatible fashion.
With these two changes, the ASP Compatibility mode allows ASP.NET to use apartment-threaded COM components or COM components that access the ASP-intrinsic objects.
Note A thorough discussion on the COM threading models is beyond the scope of this document. For more information on the various COM threading models and their implications, be sure to read Understanding and Using COM Threading Models.
Summary
You have now examined how to port an ASP application to ASP.NET. As you can see, porting an ASP page involves not much more work than simply renaming the page's file extension. Porting the Project Report Application from ASP to ASP.NET, a one-page ASP application with 200 lines of code, took under five minutes. When porting your ASP applications to ASP.NET, be sure to keep the following points in mind:
- Be familiar with the syntactical changes from VBScript to Visual Basic .NET. Guarding against small syntactical errors will make the process that much smoother.
- Add the aspcompat="true" attribute to the Page Directive if the ASP page you are porting uses apartment-threaded COM components or COM components that access the ASP-intrinsic objects. Otherwise this directive is not required.
About the Author
Scott Mitchell is the founder and editor of www.4GuysFromRolla.com, one of the largest ASP resource sites on the Web. He has been avidly using and writing about Active Server Pages since January 1998. Scott has written several hundred ASP and ASP.NET-related articles on 4Guys, along with authoring numerous beginner- and advanced-level books on Active Server Pages and ASP.NET.
About Informant Communications Group
Informant Communications Group, Inc. (www.informant.com) is a diversified media company focused on the information technology sector. Specializing in software development publications, conferences, catalog publishing and Web sites, ICG was founded in 1990. With offices in the United States and the United Kingdom, ICG has served as a respected media and marketing content integrator, satisfying the burgeoning appetite of IT professionals for quality technical information.
Copyright © 2001 Informant Communications Group and Microsoft Corporation
Technical editing: Paul Litwin, Litwin Consulting

discuss this topic to