百鸟岩介绍:ASP.NET移植须知

来源:百度文库 编辑:中财网 时间:2024/04/30 20:52:28

ASP.NET移植须知

http://www.webjx.com 更新日期:2005-02-24 10:33 出处:网页教学网 作者:虽然微软ASP.NET的设计人员在ASP 应用程序的向后兼容工作上做得相当出色,在致力于把Web应用程序从ASP迁至ASP.NET的时候,有几点需要特别注意。切实理解由.NET平台改变或引入的技术及ASP.NET,会使移植过程变得相对简单。

为增进您对如何使ASP应用程序在ASP .NET 环境中顺利运作的了解,本文着重探索了很多技术变化的方面。同时,也指出一些ASP.NET中可被用来改进现有应用程序的新功能。这并不是一篇全面认识ASP.NET新功能的文章。它主要涉及您所需要了解的实现成功移植的内容。

既然大多ASP 应用程序使用微软Visual Basic? Scripting Edition (VBScript),我估计您们大多会选择使用Visual Basic .NET移植到ASP.NET。这显然并不是必要条件,但在决定移植的同时改变编程语言会需要一些额外的努力,而且很可能会要求设计上的改变。

共存
在我们开始讨论具体的兼容与移植的问题前,您必须明白ASP与ASP.NET 如何共存。ASP与ASP.NET应用程序可以在服务器上共同运行而不互相排斥。这主要是因为这两种技术使用的文件后缀(.asp versus .aspx)与配置模式(metabase/registry versus XML-based configuration files)都有所不同。两种系统有着截然不同的处理引擎。

完全有可能使一应用程序的一部分运行ASP, 而它的另一部分运行ASP.NET。 如果您需要从一个既庞大又变化非常快的站点逐步变为ASP.NET,这一点就显得非常重要了。有人也许会认为一次性打包发布整个站点更好些。这对于Web应用的某些类型也许适用,但我想很多现有的网站,由于其规模巨大,结构复杂,网站内容与形式的革新迅速,而不适用此法。毕竟,如果您的网站有利可图,投资方恐怕十有八九会不断地让您加入新功能,而使您没法转向这个新的热门技术中去。另外,如果您打算全力转向ASP.NET,并把它当成长期投资,您会想利用这个机会尽可能的改进结构与设计。在这些情况下,用渐进的方式实现共存是必需的。

兼容性问题
把您的应用程序移植到ASP.NET也许并不容易;然而,也并不那么难。ASP.NET与ASP兼容性非常好。做到这点非常不容易,因为从ASP到ASP.NET是一场全新的变革。ASP.NET的设计者们原来计划要做到100%与ASP兼容,但最终为了长远考虑,出于优化该平台的目的,不得不收回计划。您不用担心,所有的变化都是往好的方向发展,不会在您安装时造成很大工作量。综合实际发生的变化,可以分为以下几项:
 

核心API 变化
结构变化
Visual Basic语言变化
与COM 相关的变化
应用程序配置的变化
状态管理问题
涉及安全性问题
数据访问

所有以上方面都会在下文中详细讨论。


核心API 变化

ASP的核心API由一些固有对象(Request, Response, Server, 等)及与它们相关的方法组成.除了一些简单变化,这些API在ASP.NET下会继续工作无误.所有的变化都与Request 对象有关.请看表一:

表1:API 变化

Request(item)
 在ASP中, 该方法会返回字符串数组.在ASP .NET,它会返回NameValueCollection.
Request.QueryString(item)
 在ASP中, 该方法会返回字符串数组.在ASP .NET,它会返回NameValueCollection.
Request.Form(item)
 在ASP中, 该方法会返回字符串数组.在ASP .NET,它会返回NameValueCollection.


可以看出, 这些变化对所有的方法都是一样的。

如果,您要访问的对象对某键值有唯一值,您就不需要修改您的代码。可是,如果有多个值,您就需要用不同的方法获得它们。另外,请注意Visual Basic .NET中的集合是以零为基的,而VBScript的集合是以一为基的。

例如,在ASP中,访问来自对http://localhost/myweb/valuetest.asp?values=10&values=20发出的请求的单独查询字符窜数值,可能会得到以下结果:

<%
'This will output "10"
Response.Write Request.QueryString("values")(1)

'This will output "20"
Response.Write Request.QueryString("values")(2)
%>


在ASP .NET中,QueryString属性返回NameValueCollection对象。从此对象中,您可以获得数值集合,及您想要的真正内容。再一次要强调的是:请注意集合中的第一项是基于零而不是一:

<%
'This will output "10"
Response.Write (Request.QueryString.GetValues("values")(0))

'This will output "20"
Response.Write (Request.QueryString.GetValues("values")(1))
%>

无论是ASP还是ASP.NET,以下代码执行结果是一样的:

<%
'This will output "10", "20"
Response.Write (Request.QueryString("values"))
%>
 
结构变化指的是那些影响Active Server Pages布局与代码风格的变化。您必须对它们有所了解以确保您的代码会在ASP.NET中运行无误。


代码块: 声明函数与变量

在ASP中,您可以在您的代码标示符中声明子程序与全局变量.

<%
Dim X
Dim str
Sub MySub()
Response.Write "This is a string."
End Sub
%>
在ASP.NET中,这已被禁止。您必须在


编程语言混合

在ASP编程语言中,您基本上有两种选择:VBScript 或 Microsoft? JScript?。 您可以在同一页自由混合搭配脚本块。

在ASP.NET,您现在有三种选择。您可以使用C#, Visual Basic .NET, 或 Jscript。请注意我说的是Visual Basic .NET 而不是VBScript。这是因为VBScript不存在于.NET 平台。它已经完全被Visual Basic .NET归入。虽然您可以自由选择任何语言,必须注意的是您不能再在同一页任意混合不同语言。当然您可以在您的应用程序Page1.aspx中包含C#代码,而Page2.aspx中包含Visual Basic .NET代码。您所不能做的是把它们混合放在同一页面。


新页面指令

在ASP中,您必须把所有指示指令放在页面的第一行, 而且只能在同一个代码标志符内。例如:
<%LANGUAGE="VBSCRIPT" CODEPAGE="932"%>
在ASP.NET中,您必须把语言指令与页面指令放在一行。例如:
<%@Page Language="VB" CodePage="932"%>
<%@QutputCache Duration="60" VaryByParam="none" %>
您可以根据需要,加入任意多条指令。指令可以被放在您的.apsx文件中的任何地方,但标准做法是置于文件开头。

ASP .NET纳入了一些新的指令。我建议您在ASP.NET相关文件中查找更多信息,看这些新指令是否能为您的应用程序带来益处。


Render 函数不再有效
在ASP中,开发人员发现它们可以利用所谓“输出函数”做些聪明的事。输出函数是一种正文中嵌入着大量HTML的子程序。例如:
<%Sub RenderMe()
%>

This is HTML text being rendered.


<%End Sub
RenderMe
%>
虽然用这些函数可以做很多很酷的事情,该代码在ASP.NET中不再允许使用,这应该是一种进步。我相信,在您像这样开始混合或搭配代码与HTML时,您见过有些函数很快就无法阅读与管理了。让它在ASP.NET中工作的最简单方法是调用 Response.Write 去取代您的HTML 输出。例如:



<%
Call RenderMe()
%>

请注意我说了:“最简单的方法”,这并不是说它是最好的方法。取决于您的输出代码的复杂程度与数量,使用自定义的Web controls可能对您有利。它使您可以用程序设置HTML属性,并真正把您的内容与代码分开。这样可以大大提高您的代码可读性。
 
正如我所提到过的,VBScript 已被更全面更强大的Visual Basic .NET所取代。在这部分,我会强调那些您可能会碰到的与Visual Basic语言变化相关的问题。请注意我并不会列出关于Visual Basic所有的变化,而只会着眼于一个由Visual Basic .NET转向ASP .NET的ASP/VBScript 程序员可能会遇到的情况。欲知所有语言变化,请参考Visual Basic .NET相关文档。


告别Variant数据类型

我们知道它,我们爱它,我们也恨它。我说的当然是VARIANT数据类型。VARIANT数据类型不是.NET的一部分,所以在Visual Basic .NET中也不支持它。这也就意味着您所有的ASP变量正在不知不觉地从VARIANT数据类型转为对象类型。您的应用程序里的大多变量应根据需要改为相应的基元类型。如果您的变量在Visual Basic术语中确实是对象类型,只需在ASP.NET中简单声明其为Object即可。


Visual Basic 数据类型

一种一定会引起特别关注的VARIANT是VT_DATE数据类型。在Visual Basic中它被表示为Date类型。在Visual Basic中,Date 是以4个字节的双字节格式存储的。在Visual Basic.NET中, Date使用Common Language Runtime DateTime 类型,用8个字节整数来存储。

既然在ASP中,所有变量都是VARIANT数据类型,您使用的Date变量会被编译,也可能继续工作(这取决于他们是如何被正确使用。)可是,您在使用这些变量时,也有可能会遇到各种各样的问题,因为它们实际的数据类型已经改变。在把数值作为长整数类型送入COM对象或是对日期类型用CLng实施某些转换操作时,尤要注意。


Option Explicit 现为默认

在ASP中,Option Explicit 没有被规定为默认设置。Visual Basic .NET在这点上作了改变。Option Explicit成为默认值,因此,所有变量都需要声明。如果更严格一些的话,可以把您的设置变为Option Strict,这样可以迫使您声明所有的变量为某种数据类型。虽然这看似冗余,却是您应该坚持的做法。如果您不这样做,您的代码远远不可能优化,因为所有未经声明的变量会变成Object 类型。大多数隐性转换仍会有效,但如果您声明清楚所有变量的话,以后您就可以更安心了。


LET 与 SET不再被支持

对象可以像这样直接赋值:MyObj1 = MyObj2。如果您的程序里有SET 或LET 关键字, 它们必须被移掉。


用括号实现方法调用

在ASP中,您无须使用括号就可以自由调用对象的方法。例如:

Sub WriteData()
Response.Write "This is data"
End Sub
WriteData
在ASP .NET中, 做任何调用,您都必须使用括号,即使是不使用任何参数的方法也是一样。按照如下例所示方法书写代码,可以使代码在ASP与 ASP.NET环境中都工作无误。

Sub WriteData()
Response.Write("This is data")
End Sub
Call WriteData()


ByVal成为默认

在Visual Basic中,所有参数默认以引用(或ByRef)方式来传递。在Visual Basic .NET中有所改变。所有参数默认以值(或ByVal)传递。如果您仍然希望以引用来传递,您必须在参数之前清楚注明ByRef关键字。例如:

Sub MyByRefSub (ByRef Value)
Value = 53;
End Sub
这就是您必须非常小心的地方。当您将您的代码转向ASP.NET,我建议您对方法调用中的每个参数作两次甚至三次的检查,以确保这种变化确实符合您的期望。我估计,在检查过程中,总会查出些错误。


不再有默认属性

默认属性的概念不再存在于Visual Basic .NET。 这也就意味着如果您有依赖于来自某对象的默认属性的ASP代码,您将需要加以修改,以显式地引用所需属性。请见下例:

'ASP Syntax (Implicit retrieval of Column Value property)
Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Open("TestDB")
Set RS = Conn.Execute("Select * from Products")
Response.Write RS("Name")

'ASP.NET Syntax (Explicit retrieval of Column Value property)
Conn = Server.CreateObject("ADODB.Connection")
Conn.Open("TestDB")
RS = Conn.Execute("Select * from Products")
Response.Write (RS("Name").Value)


数据类型的变化

在Visual Basic .NET,整数值现在是32 位。Long数据类型为64 位。

当从ASP.NET中调用COM对象的方法或是在您自定义Visual Basic components组件中调用Microsoft? Win32? API,都可能发生问题。您特别要注意实际需要的数据类型,以确保您正确传递数值。


结构化的例外处理

虽然在Visual Basic .NET中,仍然沿用熟悉的On Error Resume Next 及On Error Goto 错误处理方法,但是,它们不再是最好的方法。Visual Basic现在有成熟的,系统的例外处理方法。它们使用Try, Catch, 及 Finally等关键字。如果有可能的话,您应该转向这种新的错误处理模式,因为它运用了一个性能更加完善,稳定的机制来处理应用程序错误。
 
与前面介绍的.NET 框架与ASP.NET相比,COM基本没有变化。但是,这并不是说您从ASP.NET上运用它们时,您完全不需要顾及COM对象及它们的行为。以下是几点您必须注意的要素:


线程模式变化

ASP.NET线程模式是Multiple Threaded Apartment (MTA). 这就是说,您所用的为Single Threaded Apartment (STA)而生成的组件,在ASP.NET中,如不采取特别预防措施,不再会可靠工作。这包括,但不局限于,用Visual Basic 6.0及先前版本生成的所有COM组件。


ASPCOMPAT 属性

现有的STA组件不需要任何修改就能使用。 您所要做的仅仅是在ASP.NET页面的<%@Page>标签中加入指示兼容的属性aspcompat=true。比如,<%@Page aspcompat=true Language=VB%>。使用这个属性会强制该页面在STA模式下执行,从而确保您的组件正常工作。如果您的页面不指定本属性而直接引用STA组件,在运行时将发生异常。

设置aspcompat=true也将使您的页面能够调用那些需要使用ASP内建对象的COM+1.0组件。这可以通过ObjectConect对象来实现。

设置本属性会导致一定的性能下降。我建议您仅在必要的情况下使用它。


预先绑定与滞后绑定

在ASP中,所有对COM组件的调用都是通过IDispatch接口进行的。由于所有调用都需要在运行时由IDispatch间接处理,我们称之为滞后绑定。在ASP.NET中,如果您愿意,您仍然可以使用这种方式来完成对象调用。
Dim Obj As Object
Obj = Server.CreateObject("ProgID")
Obj.MyMethodCall

以上代码能够工作,但这并不是我们所推荐的用法。在ASP.NET中,您可以利用预先绑定直接创建您需要的对象:
Dim Obj As New MyObject
MyObject.MyMethodCall()

预先绑定能使您的页面在与组件的交互过程中避免出现类型错误。为了使用预先绑定,您需要在项目中加入一个引用,正如您在VB6.0项目中加入一个COM组件引用一样。假设您使用的开发工具是Visual Studio.NET,VS.NET将会在后台创建一个位于COM组件之上的代理对象,让您感到就像在使用.NET组件一样方便。

至此您可能会提出性能问题。为了保证与COM的互操作性,我们引入了代理对象,这的确会带来一定的性能负担。然而,在大多数情况下,您并不需要担心由此而引发的性能下降。毕竟,与冗长的IDispatch调用相比,代理对象所执行的CPU指令几乎可以忽略不计。您所赢得的远远超过您所失去的性能。当然,理想的状况是完全使用新创建的,被管理的(Managed)对象。然而,理想状况近期还不可能达到——我们必须保护在过去几年里对COM技术的投资。


OnStartPage和OnEndPage方法

在使用传统的OnStartPage和OnEndPage方法问题上,您可能需要多花一些时间。如果您依赖于这两个方法来访问ASP固有对象,那么您需要使用ASPCOMPAT指令,然后用Server.CreateObject以预先绑定的方式来创建对象。见下例:
Dim Obj As MyObj
Obj = Server.CreateObject(MyObj)
Obj.MyMethodCall()

请注意我们没有用“ProgID”,而是用了预先绑定的实际对象类型。为了保证以上代码正常工作,您需要在Visual Studio项目中加入对该COM组件的引用,以便VS创建一个预先绑定的包装类。这里是您必须继续使用Server.CreateObject的唯一理由。


COM小结

表2列出了您为了继续有效使用现有的COM组件所必须做的事情。

表2. 传统COM对象的ASP.NET设置

COM 组件类型/方法
 ASP .NET 设置/例程

Custom STA (Visual Basic 组件 或其它被标志为"Apartment"的组件)
 使用 ASPCOMPAT属性, 和预先绑定
Custom MTA (或其它被标志为"Both" or "Free" 的ATL 或自定义的 COM组件)
 使用预先绑定,不当但不要用 ASPCOMPAT属性
内置对象 (通过ObjectContext 对象来访问)
 使用 ASPCOMPAT属性, 和预先绑定
OnStartPage, OnEndPage
 使用 ASPCOMPAT属性, 和Server.CreateObject(Type)

无论您的组件是否使用COM+来部署,以上设置都适用。

在ASP中,Web应用程序的配置信息都存放在系统注册表或IIS的配置数据库(Metabase)中。在很多情况下,由于服务器缺乏适当的管理工具,察看或修改这些设置成为非常困难的一项工作。ASP.NET引入了全新的,基于简单、可读的XML文件的配置模式。ASP.NET应用程序在自己的目录下有一个Web.Config文件。您可以通过修改Web.Config文件来控制应用程序的自定义配置,行为,和改变它的安全属性。

由于习惯的作用,您可能像我一样还是忍不住要打开Internet Service Manager来查看或修改ASP.NET应用程序的配置。然而,您必须理解,我们现在有两套独立的配置模式。除了一些安全设置,绝大多数由IIS管理工具所生成的设置都会被ASP.NET应用程序忽略。您需要把这些设置放在Web.Config文件里。

关于.NET应用程序的设置有专门的文章讨论,我这里不再赘述。表3列出了一些比较有趣的配置。请记住还有非常多的配置项目没有列在这张表中。

表3. Web.Config 文件设置范例

项目
描述


 定制应用程序配置

 设定ASP.NET应用程序对身份验证的支持

 设定页面相关的配置

 设置ASP.NET在IIS系统中的进程模式

 指定一些会话状态选项 

.NET基本类库中有一些类可以用来在程序中简化应用程序配置访问方式。

如果您的应用程序使用了Session或Application固有对象来存储状态信息,那么它仍然能够在ASP.NET中正确运行。在ASP.NET中,您有了更多的选择来存储状态相关的数据。


可用的状态管理方法

ASP.NET提供了更多的状态存储摸式。这使您的应用程序能够跨越多个Web服务器支持Web farm范围内的状态管理。

您可以用Web.Config文件中的部分来配置状态管理选项。见下例:
mode="Inproc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;user id=sa;password=" cookieless="false"
timeout="20"
/>

mode属性指定了您想要存储状态信息的位置。您可以选择的状态包括Inproc, StateServer, SqlServer, 及Off。

表 4. 会话状态存储信息

选项
描述

Inproc
 会话状态存储于服务器本地。(ASP 风格)。
StateServer
 会话状态存储于远程或本地的状态服务进程。
SqlServer
 会话状态存储于SQL 服务器数据库。
Off
 会话状态被关闭。

当你选用StateServer状态,StateConnectionString 会起作用;而当您使用SqlServer状态, sqlConnectionString会起作用。对于每个应用程序,您仅可以使用一个存储选项。


存储COM组件

需要记住的一点是如果您依赖在您的Session 或Application对象中的传统COM组件的存储引用,您就不可以在应用程序中使用新的状态存储机制(StateServer 或SqlServer)。您只能使用Inproc。这是因为在.NET中, 那些对象需要能够自我序列化, 但显然COM 组件做不到. 相反, 您新创建的管理(Managed)组件可以相对容易实现这一点,当然也就可以使用新状态存储模式。

性能

提到性能,当然没有免费可言。可以保证的是,在大多数的情况下,Inproc会继续保持其性能之最。紧随其后的是StateServer和SqlServr。您应当用您的应用程序进行专门测试,以作出最符合您性能要求的选择。


在ASP和ASP.NET中共享状态 

另一个应当注意的问题是虽然您的工具能够容纳ASP和ASP.NET网页,但是您不能共享固有会话或应用对象的状态变量。您可以将信息在两个系统中进行复制,也可以在您的应用程序完全移植前,提供一个自定义的解决方法。底线是:如果您对Session和Application对象运用很少,您不会受到很大影响。但就另一方面而言,如果您对这些对象运用很多,您则需要谨慎的运用。您或许可以考虑采自定义一个短期解决方法以共享状态。

安全性是又一个值得关注的地方。这里提供的是对ASP.NET安全系统的简要概括。要获得更详尽的信息,请参阅ASP.NET安全系统的有关文件。

ASP .NET的安全性主要由web.config文件中的安全设置部分来控制。ASP .NET与IIS协调一致,紧密配合,为您的应用程序提供一个完整的安全模式。一些极少数的IIS 安全性设置会以在ASP中同样的方式被ASP.NET继承和运用。当然,它还有许多附加的增强组件。


身份验证

对于身份验证,ASP.NET支持列表5中的不同选项。

列表5. ASP .NET 身份验证的选项

类型
描述

Windows
 ASP .NET用Windows 身份验证.
Forms
 基于Cookie,自定义登录表.
Passport
 微软对外提供Passport 服务.
None
 没有进行身份验证

除了新的Passport 身份验证选项以外,这些选项在ASP中是相同的。以Windows为基础的身份验证在以下例子中的配置下能得到运用。







授权

当您的用户通过身份验证之后,您可以对希望他们访问的资源进行授权。以下例子说明访问权限被授予“jkieley”和“jstegman”,任何其他人都将被拒绝访问。






扮演

扮演是指一个对象以另一个实体身份标识来执行代码的过程. 在 ASP中, 扮演将允许您的代码由授权用户运行.同样的,您的用户能够在一个特殊的标识下匿名运行。在默认情况下,ASP.NET对模拟并不是有求必应。这与ASP是不同的。如果您依赖这个功能,您需要在您的web.config文件中,如下所示,激活该功能。




在移植时另一个要注意的关键是数据访问。通过ADO.NET的介绍,您现在有了一个高效的新方法来获取数据。因为数据访问就它本身而言是个很大的话题,所以它已超出了本文的范围。对大多数情况而言,您能像以前一样继续使用ADO,但是我仍推荐您看一下ADO.NET。这是在您ASP.NET应用程序中改进数据访问方法的一种有效途径。


使用ASP .NET的准备工作

现在您已知道了大多数您可能碰到的问题,您也许想知道在最终转向ASP.NET之前的今天您该做些什么以做好准备。为了让过程更顺利,有很多工作可以做。即使您将来不转向ASP.NET,这里的许多建议对您的ASP代码也是有帮助的。


使用Option Explicit

这是个很好的建议,但并不是每个人都使用它. 当在ASP中使用Option Explicit来强制变量声明时, 您会至少清楚地了解所有内容在哪里定义,及变量如何定义。一旦转到ASP.NET, 我建议您使用Option Strict. Option Explicit 在Visual Basic.NET中是默认的。 但是,如果使用更具强制性的Option Strict, 您就能确保所有的变量都被声明为正确的数据类型. 虽然这势必增添额外工作量,但是长远看来,您将会发现这是很值得的。


避免使用默认属性

正如我们所讨论的,默认的属性将不再被允许。访问属性原本就不是很困难的事。这会使您的代码更具可读性,同时,将来移植时也会更节省时间.


使用括号 和Call关键字

就如本文前面所描述的一样,应尽可能的使用括号和Call 语句。 在 ASP .NET 中您将会被迫使用括号。现在就使用Call语句助您早日养成优良编程习惯,以更好的适应将来的需求。


避免嵌套式包含文件

这点说来容易,做起来难。但是,您应该尽可能地避免嵌套您的包含文件。说得更清楚一点就是, 您应当最大幅度避免重复嵌套文件。久而久之,往往发生的情况是,您的代码不得不依赖于一个全局变量,而该变量又是在其他地方的包含文件中被定义。您能够访问它是因为您的某个包含文件包含了这个您正真需要的包含文件。

当您转向ASP .NET,您将很有可能将您的全局变量和程序移入类库中。这时如果您了解在哪里访问所有内容,就会方便很多。最后您也许不得不重新放置些文件,并改变一些重名例程的名字。


将功能函数组织成单个文件

在移植过程中的一个策略就是把功能函数和代码转移到Visual Basic 或C#类库中。相对于多重解释型的ASP文件,您最终可以把所有的代码放进它所属的对象。提前组织您的代码会节省您未来的时间。在最理想的状态下,您应该可以将子程序编组为逻辑文件。这样您就能够非常容易地创建一组VB或者C#类。这些功能在COM 对象中恐怕早就该有了。

如果在服务器端的包含文件中您有很多混合的全局变量或常数,不妨将他们也放到一个文件中。一旦您转向ASP.NET,您将能很容易的创建一个能容纳您所有全局变量或常数的类。这样您会有一个更有条理,更容易维护的系统。


尽可能地从内容中移掉代码

您应尽可能的将您的代码从HTML的内容中分离开来,这是另一个易说难做的工作。把混有代码和脚本的函数体清除出函数。这样做的话,您就会跟好的实现代码隐藏,因为这是一个ASP.NET下的理想模式。


请勿在<%%>块中声明函数

在ASP.NET中,这种写法已经不支持了。您应该把您的函数声明在