Converting ASP to ASP.NET
Summary: This document begins with an examination of a typical data-driven ASP application and then discusses porting the ASP application to ASP.NET. (13 printed pages)
- Running ASP and Microsoft ASP.NET on the same Web server
- Examining a common ASP application
- Porting the ASP application to ASP.NET
The following should be true for you to get the most out of this document:
- You are familiar with Microsoft® Visual Basic® programming concepts and terms
- You are familiar with ASP
One of the first things you are likely to notice when working with ASP.NET is the new file extension: ASP.NET pages use .aspx, as opposed to the .asp extension used with ASP. Additionally, when an ASP.NET page is requested, IIS hands off the request to the aspnet_wp.exe process; ASP uses asp.dll.
ASP and ASP.NET can both be used on the same Web server. That is, a Web site or Web application within a site can contain both ASP.NET pages and ASP pages. Because both ASP and ASP.NET pages can be accessed from the same Web server, you are not required to port your existing ASP pages over to ASP.NET-compatible pages. However, there are many advantages to porting your application from ASP to ASP.NET. Some of the biggest advantages include:
- Increased performance: Microsoft tests have shown that ASP.NET applications can handle two to three times the requests per second as classic ASP applications.
- Increased stability: Processes are closely monitored and managed by the ASP.NET run time, so that if one misbehaves (leaks, deadlocks), a new process can be created in its place, which helps keep your application constantly available to handle requests.
- Increased developer productivity: New features like server controls and event handling in ASP.NET help developers build applications more rapidly and in fewer lines of code. It is also easier than ever to separate code from HTML content.
Unfortunately, porting existing ASP pages to ASP.NET pages is almost never as easy as simply renaming the file extension from .asp to .aspx because, among other factors, there are significant differences between Microsoft Visual Basic Scripting Edition (VBScript) and Visual Basic .NET. The good news is that most of the needed changes are syntactical and automatic. Visual Basic .NET code that uses COM components (such as ADO or custom COM components you may have written) can virtually be left as is; C# code, however, requires a bit of extra code to work with COM components, which is beyond the scope of this document.
This document, which is divided into two sections, begins with an examination of a typical data-driven ASP application. In the later section, you'll look at porting this ASP application to ASP.NET.
Note This document focuses on porting an ASP application to ASP.NET with as few changes to the original ASP code as possible; it does not examine rebuilding an ASP application from the ground up, using features new to ASP.NET.
The sample ASP application that you will be porting to ASP.NET is a Project Report Application for a fictional company. The application is written in VBScript. This typical application displays information about ongoing and past projects, allowing the user to specify certain requirements on the Project Report display.
This ASP application is data-driven, as the project information is stored in a database; specifically, two database tables are used: Project and Department. The Department table contains information about each department in the company and the Project table contains information about each project, such as: project name, start date, estimated completion date, actual completion date, priority, the department in charge of the project (via a foreign key to the Department table), and a thorough project description.
A user browsing to the Project Information Web page is shown a listing of projects that were started in the past year. Two list boxes allow the user to customize the view of the current projects. The first list box lets the user specify to view ongoing, completed, or all projects. (An ongoing project is one whose completion date is NULL, and a completed project has an actual and past completion date.) The second list box permits the user to further customize the report by viewing projects by a particular department.
Figure 1 shows the project report user interface. In this instance, the user has opted to view all ongoing projects for the Internal Computer Services department.
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.Open
A 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 & vbCrLf
Next, 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 Select
Another 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 & vbCrLf
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:
in classic ASP you are saying, in essence:
When 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:
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:
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
|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.
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