当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > 从 PHP 迁移到 ASP.NET

ASP.NET
用ASP.NET加密Cookie数据
用ASP.NET开发Web服务的五则技巧
ASP.NET数据库缓存依赖
ASP.Net开发者常见Datagrid错误
asp.net 2.0多语言网站解决方案
在ASP.NET中值得注意的两个地方
用.net静态变量取代Application 速度更快
ASP.NET图象处理详解(1)
ASP.NET图象处理详解(2)
使用JScript.NET创建asp.net页面
ASP.NET中水晶报表的使用
数据库连接字在Web.config里的用法
浅谈在ASP.NET中数据有效性校验的方法
ASPX页Web服务调用性能优化
从 PHP 迁移到 ASP.NET
ASP.NET中编程杀死进程
ASP.NET保持用户状态的九种选择(上)
ASP.NET保持用户状态的九种选择(下)
使用更精简的代码保证ASP.NET应用程序的安全
为ASP.NET应用缓存Oracle数据

从 PHP 迁移到 ASP.NET


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-08-14   浏览: 54 ::
收藏到网摘: n/a

简介

本文讨论了从PHP(PHP:HypertextPreprocessor4)到ASP.NET的迁移,并对PHP和Microsoft®VisualBasic®.NET的基本语法以及基本功能和体系结构进行了对比。

尽管使用PHP和ASP.NET都可以构建复杂的Web应用程序(例如电子商务站点、Intranet和企业门户),但两者之间却存在若干重要差别。与PHP不同,ASP.NET并不是一种语言或分析器,而是Microsoft.NETFramework中的一组用于构建Web应用程序和XMLWebService的技术。同PHP一样,MicrosoftASP.NET页面在服务器上执行并生成标记(例如HTML、WML或XML),标记将发送给桌面应用程序或移动应用程序。但不同的是,ASP.NET为开发Web页面提供了强大的、面向对象的以及由事件驱动的编程模型,同时仍保留了PHP开发人员所习惯的那种简单性。

ASP.NET应用程序是基于强大的面向对象编程(OOP)模式,而不是基于脚本模式。这样便可以获得更为严谨的OOP功能,例如继承、封装和反射。虽然大多数基本的简单操作可以轻松地从PHP转换到ASP.NET,但要转换更为复杂的应用程序却并不这么简单,这需要仔细的规划和考虑,并采用更符合OOP的方法。

本文假设读者具有PHP方面的经验,并且对编程和软件开发有着基本了解。本文首先从代码方面对两者的基础体系结构的差别进行简单比较,并简要介绍一下OOP开发模型,然后比较两者的功能,最后将使用PHP和ASP.NET开发Web应用程序时的语法和常见任务作以对比。

注意:如果您希望跳过有关迁移的详细信息,而只想尝试ASP.NET的使用,则可以直接跳到建议的后续操作部分。体系结构对比

阅读完本文后,通过比较语法和语言,您将了解PHP和ASP.NET是很相似的,它们具有类似的功能和语法。但是,从更基本的体系结构层面来讲,PHP与ASP.NET却有着很大差别。PHP基于独立于平台的处理器/引擎,该处理器/引擎用于分析PHP脚本、提供数据库连接、符合Internet协议以及提供大多数Web应用程序平台所常见的众多其他任务。

ASP.NET是基于一系列技术(如CLR)构建的框架,提供了大量以很好的方式组织的类库,这些类库可满足要在Web应用程序中使用的大多数功能的需要。您还可以轻松地创建各种组件,对该框架进行扩展。

虽然PHP也提供了类似的功能(例如PEAR库),但PHP和ASP.NET并非完全相同,因为ASP.NET框架是完全基于OOP模式和OOP概念构建的,而PHP则不然。这种差别在PHP和ASP.NET中类和对象的访问方式方面表现得犹为明显。

PHP和ASP.NET中的面向对象编程

虽然PHP和ASP.NET都为应用程序开发提供了OOP模式,但它们对各种OOP概念(例如封装和多态)的支持却存在差别。例如,PHP仅支持部分封装(例如,支持在类中声明方法和字段)和部分多态(没有重载和抽象)。此外,由于PHP的类中不存在私有(private)、公有(public)或受保护(protected)函数等概念以及重载,因此PHP也不支持这些概念及其访问。OOP纯粹主义者可能会说,ASP.NET以及各种语言也没有完全支持OOP模式中的所有概念,对于使用OOP的大多数语言(如C++和Java)来说,情况确实如此。

这既有积极的一面,也有消极的一面。消极的一面是:对于某些Web开发人员来说,学习ASP.NET要比学习PHP困难些,因为PHP提供的是开发人员创建Web站点时所惯用的脚本模式。但是,使用过OOP语言和/或V的开发人员会发现ASP.NET比较亲切且易于学习。

ASP.NET支持OOP概念的积极的一面是,ASP.NET应用程序的大多数部分都会得到很好的设计,并且能够对内容、逻辑和数据进行清楚的分隔,因而从应用程序生命周期的长远角度看,这通常更容易为其提供支持。此外,由于ASP.NET本身支持企业技术,例如消息队列、事务(请参阅.NETFramework的System.EnterpriseServices类)SNMP和Web服务,因而可以很容易地开发具有高度可缩放性的强大的应用程序。

要大致了解面向对象编程(从VisualBasic的角度)的主要概念,请参阅Object-OrientedProgramminginVisualBasic。

编译PHP

请求PHP页面时,HTML和内联PHP脚本将编译为ZendOpcode(Zend操作代码)。Opcode是低级的二进制指令,是提供PHP页面时实际使用的代码。编译后,Zend引擎将运行Opcode(与Java的运行时引擎运行字节码类似),然后生成HTML并提供给客户端。

有许多商业产品可用来通过优化这些Opcode来加快PHP页面的执行速度。其他提高PHP脚本性能的方法还包括对Opcode和生成的HTML进行缓存。

ASP.NET

当向IIS(Internet信息服务)或其他Web服务器请求.aspx页面(或ASP.NET支持的任何其他扩展名)时,该请求将被传递到ASP.NET进行处理。如果是第一次请求该页面,ASP.NET会将其编译为MSIL(Microsoft中间语言)。然后,CLR(公共语言运行库)会将此MSIL代码转换为机器码。最后使用这个编译后的代码运行该请求。后续的请求将使用相同的机器码运行(假设该页面未被修改)。

需要注意的是,因为由CLR生成的二进制代码已经最大限度地进行了优化,所以不必再使用其他产品来帮助提高性能。

此外还要注意,ASP.NET中的所有内容在运行前都被编译为机器码。甚至HTML文本也被转换为字符串常值控件,并按照适当的顺序插入到控件树中。

功能对比

表1对PHP和ASP.NET中的某些主要功能进行了比较。

表1:PHP和ASP.NET的功能对比

功能PHPASP.NET编码语言具有旧ASP样式标记的C、C++样式脚本语言。支持某些OOP概念。支持超过25种语言,但最常用的两种语言是VisualBasic.NET和C#。大多数开发人员都选择一种语言,但可以使用用任何其他支持的语言编写的组件。编译的应用程序逻辑可编译并且可以作为可执行程序运行。在动态编译和预编译模式下均支持。全部页面输出缓存本身并不支持。支持,基于一个或多个URL参数、浏览器类型、自定义函数或任意组合来缓存页面的不同版本。部分页面输出缓存本身并不支持。通过使用用户控件提供内置支持。可使用缓存API和复杂的过期规则来缓存数据和其他对象。数据库访问为市场上的大多数数据库以及开放源代码的数据库提供了驱动程序。直接支持OLE-DB和ODBC,本身还包含了MicrosoftSQLServer™和Oracle的驱动程序。数据库输出数据集作为PHP变量返回,并且可以像任何其他变量那样将其输出。以模板化的方式绑定到服务器端控件以简化开发;如果需要,也可以手动循环。外部组件可以调用各种软件包,并且开发人员可以直接修改Zend引擎(因为它是开放源代码的)。负责Zend的编程人员还可以使.NET对象能够从PHP中调用。充分支持本身的C库和COM对象以及用任何与.NET兼容的语言(包括托管C++[ManagedC++])编写的程序集。对CORBA对象或Java类未提供内置支持。XML/XSLT在附加软件包和库中支持为XMLDOM、XSLT、验证和XML文档的轻量级面向流的分析提供了广泛和易于使用的支持。XMLWebService当前正在开发PHP软件包以支持基于ApacheAXIS引擎以及其他引擎的Web服务。当前版本提供了广泛、灵活、符合标准的支持,使得发布和使用Web服务都非常容易。会话状态基于Cookie的会话管理基于Cookie或无Cookie的会话状态(使用单个服务器内存存储、中央状态服务器或数据库后端)。此外,可扩展的体系结构还允许使用自定义的会话状态模块替换内置选项。要启用无Cookie的会话,只需更改配置。内置功能PHP的内置功能涵盖了基于Web的应用程序可能需要执行的许多常见任务。通过某些额外的处理,它还可以访问Java类库。ASP.NET可以直接访问整个.NETFramework类库,这些类库包含了大量功能。正则表达式支持POSIX和Perl兼容的正则表达式语法。支持Perl-5兼容的正则表达式,以及一些其他功能,例如从右向左匹配、预编译表达式、命名组及完全的Unicode支持。此外,还允许用户指定在正则表达式替换操作过程中调用的函数。调试PHP未提供广泛的调试功能,但可以通过各种第三方产品和Zend增强调试和测试功能。包含广泛的跟踪和环境信息,这些信息可包含在页面中或在单独的页面中显示。使用MicrosoftVisualStudio®.NET除了可以调试客户端脚本和SQLServer存储过程外,还可以轻松地在执行页面时对其进行交互式调试。错误处理不支持错误捕获,但提供了各种错误处理功能和日志。支持结构化的异常处理(其中新增了一个“finally”代码块,无论是否发生错误,都将执行该块),支持引发自定义异常,还支持为不同类型的不可恢复错误指定自定义错误页面。图像处理无内置支持,但可以使用第三方组件。包含大量用于创建和处理图像的工具。(请参阅.NETFramework的System.Drawing类。)代码重用用户定义的函数、创建类的功能以及包含文件。用户控件、服务器控件、自定义类以及包含文件。线程PHP具有很好的线程模型。完全支持。不但可以在单独的线程中同时请求多个页面,而且每个页面(如果需要)还可以生成自己的线程以执行同步或异步操作。数据缓存具有有限的数据缓存(仅限于数据本身)。包含大量的缓存API,能够存储几乎任何类型的数据(包括数据库查询结果),并且能够基于时间、使用情况、文件或其他缓存项而过期。还允许在从缓存中删除给定项时调用用户定义的函数。国际化完全支持Unicode。支持Unicode字符串和各种字符编码。日期、数字和货币函数均可区分文化环境,并根据当前文化环境的设置更改输出(而不要求调用其他函数)。支持使用资源文件对应用程序进行动态本地化。SMTP、HTTP、FTP、POP3本身支持各种Internet协议。SMTP支持依赖于IISSMTP服务。能够很好地支持HTTP。.NET不支持FTP和POP3,但是有一些免费的和销售的第三方组件可用来实现此功能。集成开发环境可以使用大量提供了广泛功能的开发工具,价格从零到几百美元不等。Microsoft提供了一个名为ASP.NETWebMatrix的免费ASP.NET开发工具。

最常用的工具是VisualStudio.NET,它为所有.NET语言、用于创建SQL以及测试数据库的数据库工具、Web设计工具、与版本控制的集成、高级调试功能以及许多其他功能提供了充分的支持。要获得完整的功能列表,请访问MSDN®VisualStudioDeveloperCenter。

其他工具(包括BorlandC#Builder和MacromediaDreamweaverMX)也支持ASP.NET。

Web服务器支持支持几乎所有Web服务器。支持IIS以及Covalent的商业版Apache2.0。操作系统支持支持几乎所有常用的操作系统,包括MicrosoftWindows®、Mac、OSX、Amiga、Solaris、FreeBSD、Linux以及AIX等。当前支持Windows2000、WindowsXP和WindowsServer2003。语法和常见任务对比

以下各部分比较了PHP和.NET的语法,并介绍了如何完成某些非常常见的编程任务。

注释

PHP允许您使用C、C++和Unixshell样式语法在代码中插入注释,注释指示器中的任何内容都不会被执行。

一般来讲,要在ASP.NET中注释出VisualBasic.Net代码,需要使用<%--打开注释块,并使用--%>关闭注释块。

表2显示了这两种环境中的注释。

表2:服务器端注释

PHPASP.NET/*

这是被注释出的

文本块

*/

<%--

这是注释

--%>

变量

虽然PHP和VisualBasic.NET具有类似的语言构造,但语法却截然不同。由于VisualBasic.NET是基于OOP模型构建的,因而变量的声明要比PHP中变量的声明更严谨(在PHP中声明变量时只需在变量名之前添加一个$符号)。

在VisualBasic.NET中声明变量时,要指定它的变量名和特性。变量的声明语句是Dim关键字。它的位置和内容决定了变量的特性。变量具有级别(例如局部变量和模块变量)、数据类型、生存期以及可访问性。

虽然这种方法最初看上去要比在PHP中指定变量复杂,但实际上它会给开发人员带来方便。ASP.NET致力于帮助开发人员创建可靠的应用程序,而指定数据类型可以使诸如变量清理、调试、异常和错误处理以及代码维护等任务变得更加简单。

表3显示了在两种环境中声明变量的示例。

表3:变量声明

PHPVisualBasic.NET$head_count

$foo

$X

$obj

Dimhead_countASInteger

DimfooAsString

DimXasDate

DimObjasobject

声明数据类型

声明语句中的AS子句用于定义所声明变量的数据类型或对象类型。您可以为变量指定以下任意类型:

  • 基本数据类型,例如Boolean、Long或Decimal
  • 复合数据类型,例如数组或结构
  • VisualBasic或其他应用程序中的对象类型或类,例如Label或TextBox
  • 您可以在一个语句中声明多个相同类型的变量而不必重复数据类型。下面的语句将变量numStudentsnumGTA和numProfessors声明为Integer类型:

    DimnumStudents,numGTA,numProfessorsASInteger'三个变量都是Integer类型。

    有关数据类型的详细信息,请参阅DataTypes。有关面向对象编程的详细信息,请参阅Object-OrientedProgramminginVisualBasic。

    声明生存期

    变量的生存期是指变量可供使用的时间段。使用Dim语句声明的局部变量仅在其执行过程中存在。过程终止时,该过程的所有局部变量都将消失,这些变量的值也将丢失。

    生存期这个概念很有用,因为它使开发人员在创建应用程序时不必考虑在大型应用程序中出现的许多问题,例如有效的内存管理。通过为变量选择正确的生存期,可以使.NET对未在使用的变量执行清理操作。

    有关生存期的详细信息,请参阅Lifetime。

    声明范围

    局部变量是在过程(过程与函数类似)中声明的变量。非局部变量是在过程之外但在类或结构中声明的变量。

    在类或结构中,非局部变量的类别取决于该变量是否被共享。使用Shared关键字声明的变量是共享变量,它只有一个副本并且在类或结构的所有实例中共享。如果不使用Shared关键字,则该变量为实例变量,并且针对类或结构的每个实例都将创建一个单独的变量副本。实例变量的给定副本仅可用于为之创建该副本的实例。

    变量的范围是指可以引用它而不必限定其名称的所有代码集。变量的范围取决于声明变量的位置。位于给定区域中的代码可以使用在该区域中定义的变量而不必限定其名称。声明范围时,将遵循以下规则:

  • 共享变量或实例变量的范围是在其中声明了该变量的结构或类。
  • 局部变量的范围是在其中声明了该变量的过程。
  • 但是,如果您在块中声明一个局部变量,则它的范围将只限于该块。局部变量在定义它的控制块中处于活动状态。控制块可以是过程、if语句以及循环语句等。

    有关范围的详细信息,请参阅Scope。

    声明可访问性

    .NET支持变量的可访问性,从而使开发人员可以控制哪些代码能够访问特定的变量。例如,如果要为某个公式设置一些常数,并且要确保这些常数不会被它们所在类以外的其他代码更改,则可以使用private按如下所示声明该变量:

    PrivatemyConstantAsInteger

    变量的可访问性由声明语句中使用的一个或多个关键字Dim、Public、Protected、Friend、ProtectedFriend或Private确定。开发过程中通常只使用public和private。

    您可以使用上述任意关键字来声明模块、结构、类或实例变量。过程中只允许使用Dim关键字,并且可访问性始终为private。

    输出

    PHP中输出数据的典型方式是使用echo()语言构造。ASP.NET中与此最相似的是Response.Write()方法(或<%=%>构造,它只是Response.Write()的简写形式)。表4显示了向页面写入值的基本语法。

    表4:基本输出

    PHPVisualBasic.NET<?php

    $hello="hihowareyou\n";

    echo$hello;

    ?

    >

    <%

    DimHelloAsString="Hihowareyou"&vbcrlf

    Response.Write(Hello)

    %>

    然而,这些用于向浏览器发送输出的方法主要是为了保持与传统ASP的向后兼容性。ASP.NET提供了新的基于控件且面向事件的模型,您只需在服务器控件上设置属性即可将数据输出到浏览器中。通过这种技术可以将布局与代码清楚地分开,从而简化了维护工作,并且在复杂情况下所需的代码要比PHP少得多。

    <scriptlanguage="VB"runat="server">SubPage_Load(senderAsObject,eAsEventArgs)TheDate.Text=DateTime.NowEndSub</script>Thecurrentdateis:<asp:Labelid="TheDate"runat="server"/>

    此示例声明了一个名为TheDate的服务器端标签(Label)控件,并在该页面的Load事件中将此标签的Text属性设置为当前的日期和时间。此代码的HTML输出与其他两个版本相同,不同的是Label控件将自身呈现为span标记(其中包含所设置的任何标签文本)。

    条件处理IF/ELSE

    PHP具有若干条件处理表达式,例如for、while、switch和foreach,但最常用的是if/else表达式。VisualBasic.NET有几个非常类似的构造,其语法也很类似。表5对PHP和VisualBasic.NET中的等价条件逻辑进行了比较。

    表5:基本条件逻辑

    PHPVisualBasic.NETif($a>$b){

    print"aisbiggerthanb";

    }elseif($a==$b){

    print"aisequaltob";

    }else{

    print"aissmallerthanb";

    }

    Ifa>b

    Response.write("aisbigger

    thanb")

    ElseIfa=bThen

    Response.write("aisequalto

    b")

    Else

    Response.write("aissmaller

    thanb")

    EndIf

    切换

    切换语句是大多数编程语言的常见语言构造,用于通过多个值对单个表达式进行测试。它常用于替换包含多个elseif/else块的if语句。

    图6对PHP的switch语句与VisualBasic的SelectCase语句进行了比较。

    表6:switch与selectcase语句的对比

    PHPVisualBasic.NETswitch($i){

    case0:

    print"iequals0";

    break;

    case1:

    print"iequals1";

    break;

    case2:

    print"iequals2";

    break;

    default:

    print"iisnotequalto0,

    1or2";

    }

    SelectCaseNumberi

    Case0

    description="0"

    response.write("iequals0")

    Case1

    description="1"

    response.write("iequals1")

    Case2

    description="2"

    response.write("iequals2")

    CaseElse

    description="iisnotequal

    to0,1or2"

    response.write("iisnot

    equalto0,1or2")

    EndSelect

    循环

    另一个非常常见的控制构造是循环。PHP和.NET都支持若干不同的常见循环类型。

    表7:For循环

    PHPVisualBasic.NETfor($i=1;$i<=100;$i++){

    print$i;

    }

    DimsumAsInteger=0

    DimcounterAsInteger

    Forcounter=1To100Step5

    sum+=counter

    Next

    Fori=1to100

    Response.write(i)

    NextI

    在VisualBasic中,这种循环类型被称为For...Next循环,而在PHP中则称为For循环。在此示例中,我们使用了+=运算符作为sum=sum+counter的简写方式。在PHP中,可以使用Break;语句来中断循环。而For...Next循环可以通过ExitFor语句中断。

    条件循环

    只要某个条件计算为true,条件循环便会持续重复一组指令。表8显示了这两种语言中的基本条件循环示例。

    表8:条件循环

    PHPVisualBasic.NET$i=1;

    while($i<=10):

    print$i;

    $i++;

    endwhile;

    DimcounteriAsInteger=1

    DoWhilecounteri<=10

    Response.write(i)counteri+=1

    Loop

    在VisualBasic中,这种循环类型称为Do...Loop语句,或while循环。PHP也支持Do...While循环,该循环与while循环非常类似,不同之处在于它是在每个循环的结尾而不是开始检查真假表达式。Do...While循环与常规while循环的主要差别是前者会确保运行第一个循环(因为只在该循环的结尾检查真假表达式),而常规的while循环则不一定运行。(因为它在每个循环的开始检查真假表达式,如果它一开始便计算为FALSE,该循环将立即结束执行。)

    下面给出了一个PHP中这种情况的示例:

    $i=0;do{print$i;}while($i>0);

    此循环只运行一次,因为在第一次循环后检查真假表达式时,表达式计算为FALSE($i不大于0),所以循环将停止执行。

    在VisualBasic.NET中,您可以执行同样的操作:

    DimcounteriAsInteger=0Doresponse.write(i)counterLoopWhilecounteri>0

    但是,VisualBasic.NET支持内置的循环功能,这是PHP所不支持的。该功能将对条件进行计算,直到条件为真时为止。

    Foreach循环

    PHP4(而非PHP3)包含一个foreach构造,它与ASP.NET以及某些其他语言中的构造非常类似。它只是为循环数组提供了一个简单的途径。foreach只适用于数组,如果试图将其用于其他数据类型的变量或未初始化的变量,则会导致错误。VisualBasic.NET中与此等价的循环是ForEach...Next语句。表9显示了在这两种语言中循环数组的示例。

    表9:Foreach循环

    PHPVisualBasic.NET$i=0;

    foreach($aas$v){

    print"\$Key[$i]$v\n";

    $i++;

    }

    foreachvina

    response.writea(v)(v&vbcrlf)

    next

    数组

    PHP中的数组的功能与VisualBasic.NET中的数组的功能截然不同。PHP中的数组实际上是关联数组,但是可以像索引或关联数组那样使用。而VisualBasic.NET中的数组是索引数组。VisualBasic.NET不支持关联数组(但您可以自己创建它们,请参阅下面的“集合”)。其他ASP.NET语言支持这些类型的数组,但VisualBasic.NET并不支持,这可能给PHP开发人员提出了一个难题,因为他们并不习惯使用这种更常见的索引数组,并且可能会希望在VisualBasic.NET中创建关联数组模型。表10显示了PHP和VisualBasic.NET中的简单数组示例。

    表10:创建数组的示例

    PHPVisualBasic.NET$a=array(0,1,2);DimMySingleArraya()AsInteger=

    NewInteger(2){0,1,2}

    与其他变量一样,VisualBasic.NET数组中的变量也是使用Dim语句声明的。变量名后面带有一对或多对括号,表明它是数组而不是标量(包含单个值的变量)。

    创建VisualBasic.NET数组时,还必须将其声明为保存特定类型的数据。如果指定的类型是Object(作为.NET中所有对象类型的基础的普通类型),则此数组可以保存任何类型的数据,但是从数组中检索值时,必须将值转换为原来的类型。

    VisualBasic.NET数组可以是嵌套的数组,也可以是多维数组。VisualBasic.NET中有许多与PHP相对应的用于处理数组的函数,但有一个例外。由于VisualBasic.NET不支持关联数组,因而不存在用于根据数组的“主键”来访问、索引或执行任何操作的函数。VisualBasic.NET中不存在这样的“主键”。

    虽然本文多次提到VisualBasic.NET不支持关联数组,但是可以创建集合来代替数组。集合与关联数组有些相似,可以使用集合来解决某些类似的问题。

    在某些情况下,将项目存储在集合中要比存储在数组中更有效。

    如果要处理一组小型的动态项目,则可以使用集合。要创建集合,只需如下面的示例代码所示声明并实例化一个Collection:

    DimmyCollectionAsNewCollection()

    然后,您可以使用Add方法向集合中添加成员。在此示例中,我们创建了四个字符串并将它们添加到集合中。您还可以选择添加一个唯一的String值作为集合成员的主键。该值作为Add方法的第二个参数传递给集合。

    Dimw,x,y,zAsStringw="key1"x="key2"y="key3"z="key4"myCollection.Add(w,"1")myCollection.Add(x,"2")myCollection.Add(y,"3")myCollection.Add(z,"4")

    虽然这看起来类似于在PHP中创建关联数组,但集合是一种截然不同的事物,因为它本身就是一个对象。对于转到ASP的PHP开发人员,我们建议在尝试在VisualBasic.NET中创建关联数组模型之前先了解一下Microsoft的VisualBasic.NETLanguageSpecification。

    管理状态

    任何Web应用程序中都很常见的一个任务就是管理状态,该任务通常是使用Cookie或应用程序状态管理构造(如Session变量)来完成的。VisualBasic.NET具有与PHP类似的用于处理状态的方法。

    设置和检索Cookie

    在这两种环境中设置Cookie都是比较繁琐的。表11显示了在这两种语言中编写然后读取Cookie的示例。

    表11:设置和检索Cookie

    PHPVisualBasic.NET<?php

    $value='somethingfrom

    somewhere';

    setcookie("TestCookie",

    $value,time()+3600);/*

    expirein1hour*/

    ?>

    andtoretivethesetcookie

    <?

    echo$_COOKIE["TestCookie"];

    ?>

    Dimvalueasstring="somethingfrom

    somewhere"

    DimmyCookieAsNewHttpCookie=New

    HttpCookie("Somethingfrom

    somewhereTestCookie")

    DimnowasDateTime=DateTime.Now

    myCookie.Value=now.ToString()value

    myCookie.Expires=now.AddHour(1)

    Response.Cookies.Add(myCookie)

    'andtoretrievethesetcookie

    Response.Write(Request.Cookies["Whatwe

    setTestCookie"}.Value}

    设置和检索Session变量

    ASP.NET中的Session变量与PHP中的Session变量非常类似。这两种环境中的Session变量都为确保Web应用程序访问中的一致性提供了相应处理和Cookie操作。

    最重要的一个差别是,当从ASP.NET的Session对象中检索值时,该值将作为普通的System.Object类型返回,而这种类型可以保存任何类型的数据。要使用该值,必须先将其重新转换为原来的基本类型。表12显示了一些Session变量的使用示例。

    表12:Session变量的使用

    PHPVisualBasic.NET<?PHP

    session_start();

    session_register('today');

    $today=getdate();

    ?>

    <?=$today?>

    Session("Today")=DateTime.Now

    DimtodayAsDate

    today=CDate(Session("Today"))

    Response.Write(today)

    Response.write(session("Today"))

    ASP.NET还提供了另一种形式的状态管理,即“应用程序状态”,它与Session变量类似,但只是在应用程序的生存期中保持一致。这使您可以存储各种内容,例如配置信息或数据库连接字符串。这些内容在应用程序运行期间不会发生变化。

    有关此主题的详细信息,请参阅《.NETFrameworkDevelopmentGuide》中的ApplicationState一节。

    正则表达式

    ASP.NET支持其他正则表达式实现(例如Perl和awk中的正则表达式)的大多数常见功能。这实际上是为了保持与Perl5正则表达式兼容。ASP.NET还支持其他正则表达式实现中未提供的正则表达式功能,例如从右向左匹配以及实时编译。由于ASP.NET与Perl正则表达式兼容,并且大多数PHP开发人员都使用了Perl兼容的正则表达式,因而通常无须将语法从一种形式转换为另一种形式。有关.NET正则表达式支持的详细信息,请参阅.NETFrameworkRegularExpressions。

    异常处理

    ASP.NET框架通过一种人们所熟悉的语言构造Try/Catch提供了结构化的异常处理,从而能够捕获代码中可能出现的异常。PHP没有提供此功能,但PHP5中将添加它。

    下面的示例说明了如何在VisualBasic.NET中进行异常处理:

    Try'此处是可能导致错误的代码CatcheAsExceptionType'用于处理错误的代码'可选:可在此处放置更多Catch块Finally'始终执行的代码EndTry

    要注意的是,Try块可以包含一个或多个Catch块,或包含一个Finally块,也可以同时包含两者。也就是说,如果您知道无法更正错误,但仍需要清除某些对象而不管是否发生错误,则可以使用不包含Catch语句的Try...Finally块。

    查询数据库

    在PHP中,通常可以通过两种常见方法访问数据库:使用数据库的特定扩展名或使用独立于数据库的PEARDB库。

    在ASP.NET中,可以通过一组称为ADO.NET的对象来访问数据库,这些对象与PEARDB库的功能基本相同。数据库查询实际上是通过一组连接、命令、参数和数据适配器对象完成的。其中的每个对象都有多个版本,具体情况取决于所访问的数据库的类型。例如,有一组对象用于具有OLE-DB驱动程序的数据库(例如MicrosoftAccess),还有一组对象用于具有ODBC驱动程序而没有OLE-DB驱动程序的数据库。针对Oracle和MicrosoftSQLServer也有专门的数据提供者,它们已经过优化,可以分别为每种特定的数据库提供高性能的访问。某些第三方还提供了其他数据库支持,例如MySQL。本节中的示例将使用SQLServer对象,因为它是ASP.NET最常用的数据库。

    System.Data、System.Data.SqlClient和System.Data.oledb是用于在ADO.NET中定义数据库访问的命名空间。要使页面能够访问这些类,您需要将System.Data和System.Data.SqlClient命名空间导入到页面中。

    <%@ImportNamespace="System.Data"%><%@ImportNamespace="System.Data.SqlClient"%>

    图13显示了在这两种语言中执行查询的示例。在PHP中,我们显示了一个使用PEAR的连接,PEAR不仅是用于连接DB的最常用方法之一,但还是与ADO.NET最为类似的方法。

    表13:执行查询

    PHPVisualBasic.NET<?php

    //connect

    require_once('DB.PHP');

    $db=DB::connect

    ("mysql://mydbvie

    w:user@localhost/mydb");

    if(DB::iserror($db)){

    die($db->getMessage());

    $sql="select*frommytable";

    $q=$db->query($sql);

    if(DB::iserror($q)){

    die($q->getMessage());

    }

    <tr>

    <td><?=$row[0]?></td>

    <td><?=$row[1]?></td>

    <td><?=$row[2]?></td>

    </tr>

    <scriptrunat="server">

    SubPage_Load(SenderAsObject,EAs

    EventArgs)

    DimmyConnectionAsNew

    SqlConnection("server=(local)\NetSDK;

    database=mydb;Trusted_Connection

    =yes")

    DimmyCommandAsNew

    SqlDataAdapter("select*from

    mytable",myConnection)

    DimdsAsNewDataSet()

    myCommand.Fill(ds,"myDataset")

    myDataGrid.DataSource=myDataset

    myDataGrid.DataBind()

    EndSub

    </script>

    <%---输出结果---%>

    <formrunat="server">

    <asp:DataGridid="myDataGrid"

    runat="server"/>

    </form>

    在PHP中,查询结果存储在一个称为resultset(结果集)的变量中,而在ADO.NET中,该变量称为Dataset对象。结果集是返回数据的只读视图,而.NETDataset实际上是返回数据在内存中的读写视图,这使.NET开发人员能够轻松地处理从数据源返回的数据。

    输出数据时,ASP.NET提供了若干方法,用于向用户或客户端显示数据。第一种方法与PHP类似,即使用SQLDataReader对象遍历结果集以写出我们要通过查询显示的数据。更常用的方法是ASP.NET的数据绑定(PHP中没有与此对应的方法)。通过该方法,开发人员可以构建用户界面并显示可在应用程序中使用和重用的控件,还可以进一步根据数据和逻辑提取显示内容。数据绑定的语法很灵活,您不仅可以绑定到数据源,还可以绑定到简单的属性、集合、表达式,甚至是方法调用返回的结果。

    要使用数据绑定,您需要向某个数据识别服务器控件(例如DataGrid)的DataSource属性指定某个数据源(例如查询结果)。您还可以选择为每个列提供一些附加的格式化信息并调用DataBind()方法。服务器控件将负责完成剩余的工作。

    例如,在表13中,我们使用了数据绑定语法输出查询结果,如下所示:

    <%---在页面中加载事件---%>myDataGrid.DataSource=myDatasetmyDataGrid.DataBind()<%---输出结果---%><asp:DataGridid="myDataGrid"runat="server"/>

    数据识别服务器控件将提供其他功能,例如支持对显示的数据进行分页或内联编辑。有关详细信息和示例,请参阅DataBindingServerControls。

    数据缓存和页面缓存

    对经常访问的数据进行缓存可以显著缩短站点的响应时间,因为不需要等待数据库查询便可进行页面处理。而缓存由页面请求生成的HTML可以进一步缩短响应时间,因为根本就无需处理缓存的页面。这两种环境均支持上述两种缓存策略,但与PHP相比,ASP.NET提供了更多用于缓存和管理数据的方法,从而使开发人员可以针对自己应用程序的性能需要选择相应的方法和策略。

    页面缓存

    缓存某个页面请求的HTML输出是减少Web应用程序的负载的一种常用方法。PHP本身不支持页面缓存,但是可以通过编程的方式或下载第三方软件包来执行此操作。通常可以在服务器上通过多种方法执行页面缓存,这些方法可用于缓存编译的代码,直至将页面输出写出到一个单独的文件中(该文件将随代码的更新而更新)。

    在ASP.NET中,可以通过低级别的OutputCacheAPI或高级别的@OutputCache指令来执行页面缓存。启用输出缓存后,将在对页面进行第一个GET请求时创建输出缓存条目。后续的GET或HEAD请求将由输出缓存条目支持,直到缓存的请求过期。

    输出缓存将检查页面的过期策略和验证策略。如果页面位于输出缓存中并标记了过期策略(指示该页面自缓存时开始60分钟后过期),则60分钟后,该页面将从输出缓存中删除。如果在过期后收到另一个请求,将执行页面代码并再次缓存该页面。这种过期策略称为绝对过期,即页面在某个时间之前有效。

    除了对整个页面进行输出缓存外,ASP.NET还提供了一个简单方法,使您可以只缓存页面的特定部分。这种方法称为拆分缓存。您可以使用用户控件(UserControl)来指定页面区域,并使用前面介绍的@OutputCache指令将这些区域标记为缓存区域。该指令指定了用户控件的输出内容在服务器上缓存的时间(以秒为单位)以及影响这一时间的任何可选条件。

    有关ASP.NET的输出缓存的详细信息,请参阅CachingASP.NETPages。

    数据缓存

    在PHP中,可以通过多种方法以编程方式将查询结果缓存到环境中,但PHP本身并未提供这种方法。在PHP中,可以创建数据缓存类或系统。对于少量信息,只需使用Session变量和/或Cookie;对于大量或复杂的信息,可以创建您自己的数据缓存类。但问题是,当处理包含很多类型的复杂数据时,这种方法的效率会很低且容易出错,在一定程度上会加大编程的难度。

    ASP.NET通过Page.Cache对象提供了一个系统范围的数据缓存方法,可用于数据集(DataSet)、数组、集合、XML对象等。对于需要更复杂功能的应用程序,ASP.NET缓存还支持三种特定类型的缓存:过期、清理以及文件和关键项相关性。

  • 过期类型的缓存使开发人员可以控制缓存项目的过期时间。可以将该时间定义为特定的时间(例如01:00),也可以将其定义为相对于上次使用项目时的时间,例如自上次访问该项目时开始20分钟后过期。过期后的项目将从缓存中删除,以后再试图检索该项目时,将返回空值(除非再次将其插入到缓存中)。
  • 清理类型的缓存会在内存不足时尝试删除不经常使用或不重要的项目。开发人员可以控制清理的执行方式,并且可以在将项目插入到缓存中时向清理程序提供提示,以指示创建该项目的相对系统开销以及为使该项目有效而必须对其进行访问的相对频率。
  • 文件和关键项相关性类型的缓存将基于某个外部文件或另一个缓存项目确定该缓存项目的有效性。如果相关项发生变化,缓存项目将失效并从缓存中删除。例如,假设您有一个较大的需要定期更新并下载给员工的报告,则可以在应用程序中使用此功能。应用程序处理文件和报告中的数据,然后缓存该数据并插入对该数据的来源文件(从该文件读取数据)的相关性。当该文件更新时,数据将从缓存中删除,应用程序可以重新读取它并重新插入更新的数据副本。
  • ASP.NET数据缓存为编程人员提供了许多不同的方法来管理应用程序并提高应用程序的响应速度和效率。有关详细信息,请参阅CacheClass文档以了解Cache对象。

    发送电子邮件

    PHP和ASP.NET都为以编程方式发送电子邮件提供了内置的支持。要在此示例中使用ASP.NET发送电子邮件,您需要设置IISSMTP服务。因为.NET中的内置邮件对象依赖于该服务包含的对象,所以您必须安装它。尽管如此,与PHP一样,.NET也允许您使用任何SMTP服务器或邮件服务器。表14对这两种环境的基本语法进行了比较。

    表14:发送电子邮件

    PHPVisualBasic.NET$to="[email protected]";

    $from=

    "[email protected]";

    $subject="hi";

    $message="justwantedtosay

    hi";

    mail($to,$subject,$message,

    $from)

    DimmyMailAsMailMessage=New

    MailMessage()

    myMail.From="[email protected]"

    myMail.To="[email protected]"

    myMail.Subect="hi"

    myMail.Body="justwantedtosayhi"

    SmtpMail.Send(myMail)

    XML处理和Web服务

    在PHP中,为分析和处理XML所提供的内置支持功能非常薄弱。虽然开发人员可以用它来分析和处理XML,但它不支持DOM分析(该分析尽管比PHP的SAX分析器速度慢,但更容易使用)。PHP也不支持根据DTD或XMLSCHEME对XML文档进行本地验证,它也不支持XSL/XSLT以及市场上许多Web应用程序常用的各种其他技术。虽然PHP可以通过很多PHP软件包完成许多与XML相关的任务,但.NET和ASP.NET为处理XML提供了广泛的内置支持。XML是.Net平台的核心技术之一。有关Web服务的详细信息,请参阅HowASP.NETWebServicesWork。

    .NETFramework为W3C定义的所有XML建议提供了广泛的支持,此外还支持XSL/XSLT、XPath、XQuery以及各种其他技术,例如用于Web服务的UDDI、WSDL以及SOAP。

    虽然可以在PHP中创建XML-RPC类型的机制,但创建Web服务(使开发人员能够使用常用协议和标准来交换数据和过程并将其用于查找、数据绑定和描述)。.NET为Web服务和相关技术(如SOAP、WSDL和UDDI)提供了广泛的支持。使用.NET,开发人员还可以轻松地创建和开发Web服务。例如,以下代码将创建一个简单的helloworldWeb服务:

    <%@WebServiceLanguage="VB"Class="HelloWorld"%>ImportsSystemImportsSystem.Web.ServicesPublicClassHelloWorld:InheritsWebService<WebMethod()>PublicFunctionSayHelloWorld()AsStringReturn("HelloWorld")EndFunctionEndClass

    利用.NETFrameworkSDK,您可以使用命令行Web服务描述语言工具(WSDL.exe)生成代理类。要为上述示例创建一个名为HelloWorld.cs的代理类,可以输入:

    WSDLhttp://someDomain.com/someFolder/HelloWorld.asmx?WSDL

    此类与前面创建的类非常相似。它包含一个名为SayHelloWorld的方法,用于返回字符串。将此代理类编译到应用程序中,然后调用此代理类的方法,使该代理类通过HTTP将SOAP请求打包并接收SOAP编码的响应,该响应随后被封装为字符串。

    对于客户端,该代码是非常简单的,如以下示例所示:

    DimmyHelloWorldAsNewHelloWorld()DimsReturnAsString=myHelloWorld.SayHelloWorld()

    这就是创建一个简单Web服务的全过程。有关XML的一般信息以及Web服务的特定信息,请参阅EmployingXMLinthe.NETFramework。

    小结

    对于简单的小型应用程序,从PHP迁移到ASP.NET通常并不复杂。对于更复杂的应用程序,由于基础体系结构的不同以及ASP.NET的OOP模式,需要进行事先规划和精心设计,以利用ASP.NET提供的将显示与逻辑和数据明确分开的功能,以及可以节省时间的内置功能。与PHP相比,这些功能可以显著减少完成相同任务所需的代码数量。