本文将先从解释典型数据驱动的 ASP 应用程序开始,再接下来讨论将 ASP 应用程序移植到 ASP.NET

目标

·                 将 ASP 及 Microsoft ASP.NET 执行在相同的网页服务器上

·                 分析一般的 ASP 应用程序

·                 将 ASP 应用程序移植至 ASP.NET

前提

您应该具备下列特质以完全了解这篇文章:

·                 熟悉 Microsoft® Visual Basic® 程序设计概念和术语。

·                 熟悉 ASP

内容

将 ASP 及 ASP.NET 执行在相同的网页服务器上分析 ASP 范例应用程序将 ASP 应用程序移植至 ASP.NET总结

ASP ASP.NET 执行在相同的网页服务器上

当使用 ASP.NET 时可能会注意到的第一件事就是新的扩展名:ASP.NET 网页使用 .aspx,相对于 ASP 使用 .asp 作为其扩展名。另外,当要求 ASP.NET 网页时,IIS 将该要求递交给 aspnet_wp.exe 处理序;而 ASP 则使用 asp.dll。

ASP 及 ASP.NET 可同时用于相同的网页服务器上。也就是说,站台中的网站或 Web 应用程序可同时包含 ASP.NET 网页和 ASP 网页。由于 ASP 和 ASP.NET 网页可同时从相同的网页服务器存取,所以并不需要将现有的 ASP 网页移植到 ASP.NET 相容的页面。然而,将应用程序从 ASP 移植至 ASP.NET 有许多好处。其中一些最大的优点包括:

·                 提高效能:Microsoft 的测试显示 ASP.NET 应用程序每秒可处理的要求量约为传统 ASP 应用程序两到三倍。

·                 加强稳定性:ASP.NET 执行阶段将严格监视并管理各处理序,以便在其中一个处理序发生不当行为 (遗漏、死锁) 时,可建立新的处理序并马上取代,这可帮助您的应用程序经常保持其可用状态以处理要求。

·                 提高开发人员产能:ASP.NET 中的新功能,如服务器控件和事件处理,可帮助开发人员更快并以更少的程序代码建置应用程序。将程序代码从 HTML 内容抽离也比以往更容易许多。

不幸的是,将现有的 ASP 网页移植至 ASP.NET 网页几乎不可能像将扩展名从 .asp 改成 .aspx 那么简单,再加上其它一些因素,Microsoft Visual Basic Scripting Edition (VBScript) 与 Visual Basic .NET 之间有着极大的差异。好消息是多数必要的变更都是有句法且自动化的。使用 COM 组件 (如 ADO 或您撰写完成的自订 COM 组件) 的 Visual Basic .NET 程序代码实际上可保留现状;而 C# 程序代码就需要一些额外的程序代码来处理 COM 组件,不过这已超出本文的范围。

本文分成两个部份,先从解释典型数据驱动的 ASP 应用程序开始。在稍后的部份,会大致浏览将 ASP 应用程序移植到 ASP.NET 的过程。

附注   本文把重点放在以尽可能少的原始 ASP 程序代码变更,而将 ASP 应用程序移植至 ASP.NET;它并不会探讨从头开始重新建置 ASP 应用程序,使用 ASP.NET 中的新功能等。

分析 ASP 范例应用程序

在这里将使用某一虚构公司的 Project Report Application 作为移植至 ASP.NET 的 ASP 范例应用程序。这个应用程序会以VBScript撰写。这种典型的应用程序会显示进行中和过去项目的相关信息,让使用者在 Project Report 画面指定某些需求。

此 ASP 应用程序属数据驱动 (data-driven),即项目信息是储存在数据库中;具体来说,会用到两个数据库数据表:Project 和 Department。Department 数据表中包含公司中每个部门的相关信息,而 Project 数据表则包含每个项目的相关信息,如项目名称、开始日期、预估完成日期、实际完成日期、优先级、负责项目的部门 (透过 Department 数据表的外部索引键),以及完整的项目说明。

浏览至 [Project Information] 网页的使用者,将显示在从去年开始的项目清单中。两个清单方块让使用者可以自订目前项目的检视方式。第一个清单方块可让使用者指定要检视进行中、已完成或全部项目 (进行中的项目其完成日期为 NULL,而已完成的项目则有实际及过去完成的日期)。第二个清单方块允许使用者依特定部门检视项目以进一步自订报告。

[图 1] 显示了项目报告的使用者接口。在这个例子当中,使用者选择检视内部计算机服务部门内所有的进行中项目。

[ 1] 内部计算机服务部门内进行中的项目报告

分析 Project Report 程序代码

整个 Project Report 应用程序的原始程序代码都内含在单一 ASP 网页中,这使用一种回传窗体来处理使用者的报告自订选项。由于本文着重于移植 ASP 应用程序至 ASP.NET,故并未涵盖 ASP 程序代码运作的方式。我们假设您具备如何将 ASP 及 ADO 数据存取用于建置现今的应用程序的相关知识。

下列程序代码显示在 Microsoft Access 数据库建立并开启的 ADO Connection 对象。

Set objConn = Server.CreateObject("ADODB.Connection")

objConn.ConnectionString = _     

     "PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=" & _ 

     Server.MapPath("Projects.mdb") & ";"

objConn.Open

Department 数据表中的每一数据列都是含有 NameDepartmentID 的数据录集 (Recordset)。此数据录集的内容之后会显示在清单方块中。

Set objDeptListRS = Server.CreateObject("ADODB.Recordset")

objDepartmentListingRS.Open "Department", objConn, _

            adOpenForwardOnly, adLockReadOnly, adCmdTable

 

'重复整个数据录集

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") & """"

 

   '我们需要将项目变成「已选取」状态吗?     

   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

接下来,将依使用者所选取的选项建构动态 SQL 查询。请注意在下列程序代码中建立了 SQL 查询的 WHERE 子句,让它永远只撷取那些从前一年开始的项目。WHERE 子句可根据使用者的选项更进一步扩充。iDepartmentIDstrProjectView 变量是先前定义且指派给使用者所选取的清单方块值。

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()) & "# "

 

'如有需要现在可以建构额外的 WHERE 子句

If CInt(iDepartmentID) <> -1 then

   'Add a clause for the department ID

   strSQL = strSQL & " AND P.DepartmentID = " & _

                                       iDepartmentID

End If

 

'我们想要检视哪种项目?

Select Case strProjectView

   Case "ongoing":

      strSQL = strSQL & " AND ActualEndDate IS NULL"

   Case "completed":

      strSQL = strSQL & " AND ActualEndDate IS NOT NULL"

End Select

建立的另一个 Recordset 对象,objProjectsRS,会填入上列动态 SQL 查询结果。最后,此数据录集会一直重复并显示为 HTML 表格。

'输出 HTML table 标记和 th 标记

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

 

'重复整个数据录集

Do While Not objProjectsRS.EOF

   '显示数据录集信息

 

   objProjectsRS.MoveNext   '移到下一笔记录

Loop

Response.Write "</table>" & vbCrLf & vbCrLf

ASP 移植至 ASP.NET

当移植 ASP 应用程序至 ASP.NET 时,会需要决定要花多少时间在现有的 ASP 应用程序并入 ASP.NET 新功能。将 ASP 网页的扩展名从 .asp 改为 .aspx,并修正一些句法上的变更通常就够让 ASP 网页如 ASP.NET 网页般运作。这一类的移植,虽然可快速完成,但并没有利用到多少 .NET 的新功能,包括 ASP.NET 的网页控件、Microsoft ADO.NET、Microsoft .NET Framework 类别等。虽然更完整的移植可能需要花更多时间,但最后完成的 ASP.NET 网页也更容易读取、更容易维护且功能更丰富。

身为一名开发人员,在决定要采取什么方法将 ASP 应用程序移至 ASP.NET 时,您需要稍加斟酌。如果有时间的压力,则从 ASP 至 ASP.NET 的简单移植可能比较合宜;如果没有什么期限,其实值得花点时间彻底建置一个丰富的 ASP.NET 应用程序。当然,您也可以采取渐进式的方法。如果您管理的大型站台利用了许多 COM 组件来实作商务规则,则可以选择先移植网页应用程序的使用者接口 (UI) 部份,并继续使用传统的 COM 组件。

在接下来的部份,将探讨以尽可能少的修改将现有的 ASP 程序代码移植至 ASP.NET。

ASP 应用程序移植至 ASP.NET

将现有 ASP 应用程序移植至 ASP.NET 的第一步就是将 ASP 网页的扩展名从 .asp 重新命名为 .aspx。由于 Project Report Application 只有一个 ASP 网页,所以剩下的工作其实非常简单。一旦进行这项变更之后,花点时间透过您的 Web 浏览器参观一下新的 .aspx 页面。加载时有发生错误吗?应该不太可能,不过 VBScript 程序代码有可能包含了一些句法问题。

当移植我们先前探讨过的 ASP 应用程序时,会收到的第一个错误讯息是关于 Option Explicit 的错误,如 [图 2] 所示。

[ 2] Option Explicit 陈述式错误讯息

对 ASP.NET 网页而言,此陈述式应该移至 @Page 指示词。现在可以开始编辑 .aspx 档案,移除行 1 和行 2,并以下列 @Page 指示词取代:

<% @Page Language="VB" Explicit="True" %>

完成这项变更之后,在浏览器中重新加载该页面。将会收到另一个关于 Response.Write 陈述式缺乏括号的错误。

[ 3] Response.Write 陈述式错误讯息

此错误的产生是因为 Visual Basic 要求副函式及函式中所有的自变量清单都必须使用括号括住。检查整个文件并为所有 Response.Write 陈述式的自变量清单周围放上括号,然后在浏览器中重新加载 ASP.NET 一次。

另一个从 Visual Basic 6.0/VBScript 到 Visual Basic .NET 的变更是 Visual Basic .NET 并不支持预设属性。预设属性允许开发人员走一点快捷方式 — 如果在 Visual Basic 6.0/VBScript 中使用传统 COM 组件而无法指定属性时,就可以使用预设属性。例如,ADO 数据录集的预设属性是 Fields 集合,而 Fields 集合的预设属性是 Value 属性。因此,当您使用:

Response.Write objRecordset("columnName")

在传统的 ASP 中您本质上的意思是:

Response.Write objRecordset.Fields("columnName").Value

当将传统的 ASP 网页移植置 ASP.NET 时,您可能会收到下列密码编译的错误讯息:

Cast from __ComObject to String is not valid.

[ 4] ASP.NET 移植程序错误讯息

发生这类错误是因为 Visual Basic .NET 并不支持预设属性,当我们使用:

Response.Write(objRecordset("columnName"))

Visual Basic .NET 尝试将 Fields 对象转换成 String,而它其实办不到。相反地,我们必须明确陈述希望输出的属性来指明想要输出的 Value 属性:

Response.Write(objRecordset.Fields("columnName").Value)

在继续移植 ASP.NET 应用程序的同时,必定会碰到其它句法上的错误。[表 1] 总结了将 Project Report Appliction 从 ASP 移植至 ASP.NET 时所遇到的句法错误。

附注   Visual Basic 在 Visual Basic .NET 的发行之时已蜕变为成熟的程序设计语言。它现在支持 try...catch 错误处理、真实对象导向开发,以及许多其它期待已久的增强功能。为了使 Visual Basic 更现代化,在语言上做些句法上的变更是必要的。也因此,Visual Basic .NET 并不是 100% 与 VBScript 或 Visual Basic 6. 0 相容。有关 Visual Basic .NET 中的变更的详细讨论, 请务必参阅《Preparing your Visual Basic 6.0 Applications for the Upgrade to Visual Basic .NET》(英文)。

[ 1] 移植 Project Report Application 时所遇到的句法错误

错误

原因

解析

Option Explicit 陈述式在程序中无效。

Option Explicit 需要使用 Explicit 属性在 Page Directive 中定义。

<% @Page Explicit="True" %> 加入 ASP.NET 网页最上方。

只能有一个 Page Directive。

当新增 Page Directive 时,@LANGUAGE = "VBSCRIPT" 指示词在 ASP 网页中是多余的。

移除包含 <%@ LANGUAGE = "VBSCRIPT" %> 的行,并在 Page Directive 加入 Language="VB" 属性。

呼叫陈述式的自变量清单现在必须使用括号括住。

Visual Basic .NET 要求所有副函式将其参数以括号括住。许多 Response.Write 陈述式并没有包含此类括号。

加入需要的括号:例如将 Response.Write str 变更为 Response.Write(str)

设定陈述式不再支持 Let 和 Set 陈述式。

由于 Visual Basic .NET 不再支持预设属性,所以 LetSet 关键词已从 Visual Basic 语言中移除。

移除任何 LetSet 关键词 (在 Porject Report Application 中,Set 关键词会将 ConnectionRecordset 对象指定给变量)。

数据是一种型别,所以不是有效的表达式。只接受变量、常数或程序。

在 Project Report Application 中是使用 Date() 函式来取得目前日期。此已不再支援。

DateTime.Now 取代 Date()

并未宣告 IsNull 名称。

Visual Basic .NET 不再支持 IsNull 函式 (记得在 Project Report Application 中,如果实际完成日期为 NULL,则代表项目未完成;在 ASP 版本中,IsNull 是用来检查该字段是否为 NULL)。

IsDBNull 取代 IsNull 可解决此问题。

从 __ComObject 转换成 String 无效。

Visual Basic .NET 不再支持预设属性,所以当使用传统 COM 组件时,请确定要完全明确陈述希望使用的属性。

objRS("colName") 的执行个体变更为 objRS.Fields("colName").Value

COM 组件执行绪议题

在 ASP.NET 网页中使用 COM 组件可能会引发一些问题,尤其是该些被标为 Apartment 执行绪的 COM 组件或透过 ObjectContext 对象存取 ASP 内建对象 (RequestResponseServerApplicationSession) 的 COM 物件。

例如,依预设,ADO 对象在登录中会被标为 Apartment 执行绪;当尝试透过 ASP.NET 网页使用 apartment 执行绪组件时,会收到一个错误指出您尝试建立的 apartment 执行绪组件无法建立。[图 5] 显示 Project Report Application 的 ASP.NET 移植程序。请注意此错误的出现是因为 ADO 对象依预设标为 apartment 执行绪。

[ 5] 当尝试透过 ASP.NET 网页存取 apartment 执行绪 COM 组件时发生错误

还好 ASP.NET 提供一种「ASP 兼容性」模式,如错误讯息所说的。若要启动 ASP 兼容性模式,将 aspcompat=true 属性新增到 Page Directive。新增此属性完成了两件事:

·                 ASP.NET 使用单一执行绪 Apartment (STA) 存取 COM 组件。预设是使用多执行绪 Apartment 或 MTA 执行绪。

·                 ASP.NET 以与旧版兼容的方式提供 ASP 内建对象的存取权。

有了这两项变更,ASP 兼容性模式允许 ASP.NET 使用 apartment 执行绪的 COM 组件或存取 ASP 内建对象的 COM 组件。

附注   关于 COM 执行绪模型的完整讨论已超过本文范围。如需关于不同 COM 执行绪模型及其含意的详细信息,请务必参阅《Understanding and Using COM Threading Models》(英文)。

总结

现在已探讨过如何将 ASP 应用程序移植至 ASP.NET。如您所见,移植 ASP 网页所牵涉的工作不过就比单单重新命名档案扩展名再多一点。将 Project Report Application 从 ASP 移植至 ASP.NET,一个只有一页的 ASP 应用程序再加上 20 行程序代码,只需不超过五分钟的时间。当移植您的 ASP 应用程序至 ASP.NET 时,请记得下列要点:

·                 了解 VBScript 到 Visual Basic .NET 的句法变化。注意这些小小的句法错误将让整个过程更平顺。

·                 如果移植的 ASP 网页使用的是 apartment 执行绪 COM 组件或存取 ASP 内建对象的 COM 组件,则将 aspcompat="true" 属性加入 Page Directive。否则不需要此指示词。