Translator:Ryan Chung
摘要:尽管ASP.NET 2.0 是100%相后兼容ASP.NET 1.1的,但是ASP.NET 2.0 引进了一些内部的改变。本篇文章将在代码模式,编译和页面生命周期等方面做一些概述。
介绍
对于专业的ASP.NET 2.0 开发人员,有关于ASP.NET 2.0的一个大问题就是ASP.NET 2.0的内部改变了什么。学习新的特性既开心又有趣,但是ASP.NET核心结构的改变对于像真正掌握技术的人来说更加重要。在本章中,我们将介绍ASP.NET 2.0 自从1.x版本开始的核心如何改变的。
本章的主题对于关心性能的开发人员和寻找优秀协调程序的构架师来说,将会非常有用。特别的,我们将研究代码模式、编译、页码的生命周期。扩展性、缓存和性能增强等方面的核心区域。
本文章的许多实例需要对于ASP.NET、Visual Basic.NET 或者C#语法的熟练掌握。对于特别的主题,我们将提供可运行的,参考性的文档做进一步的讨论。
代码模式(Code Model)
可能ASP.NET 2.0 内部工作方式的最明显的改变就是ASP.NET创建页面的方式。我们将会研究代码掩盖(code behind)的这些改变,以及这些改变如何冲击ASP.NET开发。
ASP.NET 1.x的代码模式
在ASP.NET 1.x 时代,开发人员有两种主要方法编写一个页面窗口(Web Form)。第一种方式就是使用传统的ASP模式,在ASPX页面中直接编写代码。这种方法叫做代码内联(code inline),对于简单的命令工作地很好。但是对于复杂地代码,编写内联代码将导致Web页面难以阅读,由于他们将页面的表示(HTML)同功能(code)混为一谈。
在ASP.NET中,默认的编码方法改变后有助于解决这个问题。业务逻辑和事件处理的代码写在一个单独的、只有代码的文件中,叫做code behind文件。这个code behind 模式将ASPX文件同一个只有代码的文件连接起来,这个ASPX文件包含了一些表达标签。通过将代码同表示层分离,开发团队可以让设计人员负责表示文档的设计,而开发人员负责代码文件,这样开发更快。

图1. ASP.NET 1.x 代码模式
Code behind的首要困难就是解决code behind文件同ASPX页面同步的方法。尽管从编程角度来看,ASPX页面继承于code behind文件,但是这两种文件实际通过一种更加复杂的关系连接起来。
继承的复杂度
ASP.NET的设计范例,就是开发人员使用Visual Studio.NET 往ASPX页面上拖放控件。Visual Studio将自动在code behind 文件中生成合适的支撑代码。如果ASPX页面中添加了控件,code behind 文件中也必须加入新的代码。换句话说,尽管继承关系指向其他地方,但是ASPX文件实际引导着code behind文件的设计。
编译复杂度
第二个同步问题就是编译文件的方法。所有的code behind 文件,以及他们的支持类,都在一个部件(assembly)中编译,然后在此Web程序的/bin目录下存储。一方面编译先于程序的部署,另一方面,ASPX页面在第一次被请求的时候在运行时(runtime)中编译。实际上ASP.NET运行时在他自己的临时配件中编译ASPX页面。
在这个过程中,ASPX页面可能在没有更新code behind 配件的情况下被改变。这就是,一个开发人员可能在部署之后,选择去修改一个属性或者改变一个控件的类型,但是code behind文件并不会改变,并且它的配件也不会重新编译。如果这个发生,程序将遭受不可预料的错误,因为code behind 文件和他们对应的ASP页面不匹配。
ASP.NET 2.0的代码模式
ASP.NET 2.0 继续提供代码内联(code inline)和代码掩盖(code behind)模式。对于代码内联模式,除了Visual Studio 2005 支持单文件开发的方式,只有很小的改变。特别的是ASPX页面现在更好地支持了IntelliSense。当你开始在括号内编写代码时,Visual Studio 将提供完成,帮助和插入代码的全部IntelliSense支持,
ASP.NET 2.0宣称ASP.NET 2.0的继承和编译,通过修改code behind 文件的特性,同code behind 模式发生关联。在 ASP.NET时代,code behind 不再是System.Web.UI.Page 类的实现,而是一个新的结构体叫做部分类(partial class)。部分类包括素有用户定义的代码,但是忽略掉所有通过Visual Studio.Net 在ASP.NET 1.x时代生成的测量和连接代码。当含有一个新的含有code behind 文件的ASPX页面被请求时,ASP.NET 2.0 运行时(runtime)实际上将ASPX和这个部分类连接成一个类,而不是两个独立的类。

Figure 2. ASP.NET 2.0 的模式
这个部分类使用一个新的关键字(Visual Basic 是Expands,或者在C#中是Partial),来表明在运行时此类中的代码要同另外一个类合并起来。简单说来,ASPX页面使用一个新的命令叫做compiewith,来表明它同code behind 文件的联系。最后的结果永远是一个编译的代码文件在一个配件里,而不是两个文件在不同的配件里。
比较Code Behind文件
如果你熟悉传统的ASP.NET 1.x code behind文件,你知道Visual Studio会插入自动生成的控件声明和实现代码。这个自动生成的代码是code behind文件和ASPX文件双向同步的直接结果。一个典型的ASPX页面的标签控件,将有一个对应的code behind 文件,包括许多行自动生成的代码:
namespace WebApplication1
{
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Label Label1;
private void Page_Load(object sender, System.EventArgs e)
{ }
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
}
}
Listing 1. ASP.NET 1.x的一个Code Behind 文件
这个自动生成的代码不仅定义了标签控件(粗体的行),还声明了一个新的事件(Load),而且自动将这个事件添加到一个自动生成的方法包(Page_Load())。
对于每个你在ASP.NET 2.0中创建的code behind .aspx文件,ASP.NET生成一个更加干净的部分类,同你在code behind 文件中定义的部分类合并起来。这两个部分类合并成一个单独的类定义,在编译的时候作为你.aspx文件中的类提供服务的基类。
namespace ASP {
public partial class Webform1 : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
Listing 2. ASP.NET 2.0 的Code Behind 文件
The developer can access Label1 automatically and can add events as needed. For example, a Page_Load event can be added to initialize the label:
开发人员可以自动访问Label1,并且根据需要添加事件。例如,一个Page_Load事件可以添加来初始化此Label控件。
Namespace ASP{
public partial class Webform1 : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = "Hello ASP.NET 2.0";
}
}
}
Listing 3. 在一个新的 code behind 文件中添加事件
通过Visual Studio 2005可以生成事件的语法。最终的code behind 文件将会更加地短,并且跟任何自动生成的代码独立。ASP.NET运行时自动把ASPX中的控件同这个事件连接起来。换句话说,ASP.NET在运行时自动完成运行代码的生成,这个过去却是通过Visual Studio来完成的。
新的两步编译的好处就是这个可以让你把code-behind的类编译到一个二进制文件中,并且为了以后的修改支持像html一样部署.aspx文件,就像.aspx源文件是部分类型,跟 code-behind同时编译。
继承的复杂度
新的code behind 模式极大地减少了继承复杂度。因为ASPX页面不是直接地从code behind文件继承过来,code behind不再需要定义和支持ASPX文件中定义的控件。同样的,code behind 文件能够自动访问ASPX文件中的任何控件,而不必需要ASP.NET1.x所需的声明代码。所有这一切的实现是因为ASP.NET运行时自动添加所需的声明和事件到最终的编译文件。因为运行是负责这些任务,代码开发人员和Web开发人员不再需要担心这个问题了。
在设计事件,通过Visual Studio 2005 维护这种连接。Visual Studio环境平衡ASP.NET运行时的编译片,来保证代码开发人员和Web开发人员能够同步工作。
编译复杂度
因为新的code behind 文件同ASPX文件连接起来,并且在运行时内编译成一个单一而完整的类,编译复杂度消失了。Code behind 文件自动跟ASPX同步。甚至在新的编译模式中,仍然可以使用非同步的代码,但是这个主题能很快确定,因为最终的例外非常明显。
编译
感谢ASP.NET 1.x的页面模式,一个ASP.NET Web 页面的编译总是分成两个阶段。第一个阶段,code behind文件和其他的类编译成一个配件,然后单独的ASPX文件在运行时中编译。虽然这个模式有许多优点,但是有一些缺点。ASP.NET 2.0 对基本模式提供了许多选择,根据你特别的需要提供更广泛的编译选择。
ASP.NET 1.x的编译
ASP.NET 1.x的第一个编译模式导致了一个程序配件(包括所有编译的code behind代码和其他源文件),和在请求时对每个ASPX文件创建的一个临时的配件。在大多数情况下,编译器的优化,例如批处理,可能引起不同的临时ASPX文件在同样的配件中编译。在任何情况下,每个ASPX文件都被编译成一个临时配件,这样才能装载到ASP.NET 运行时中。

Figure 3. ASP.NET 1.x的编译
虽然这个模式有优点,但是有两个根本的缺点。第一,ASPX文件必须按照人类可读的方式部署到站点。如果你的开发人员使用代码内联模式,这就意味着一些或者所有你的业务逻辑可能同样要部署到一个最终服务器上。虽然IIS和ASPX.NET设置成禁止暴露原始的ASPX文件,但是一个聪明的黑客仍然可以通过各种方法访问Web服务器,然后访问文件。第二,任何人第一次请求一个Web页面的时候,它的相应时间比正常时间慢,因为ASP.NET运行时要编译这个ASPX文件。
一个开发人员唯一可以控制的过程就是是否批处理编译ASPX文件。在ASP.NET 1.x时代,你能在Web.config文件中修改
Listing 4. 配置批处理编译
在第一次Web页面请求时,批处理编译交换开始的时间来减少载入的时间。批处理编译的另外一个好处就是所有的ASPX文件都将编译成一个单独的临时配件,而不是每个页面生成一个配件。
ASP.NET 2.0的编译
对于一个Web程序,ASP.NET 2.0 提供了四种不同的编译模式:
1、一般模式(Normal)(ASP.NET 1.x)。在一个normal ASP.NET Web 程序中,code behind 文件编译成一个配件,并且存储在/bin目录中。Web 页面(ASPX)根据需要进行编译。这个模式对于大多数网站都有效。但是,这个编译过程造成任何ASP.NET页面的第一次请求度比后来的请求慢。ASP.NET 2.0 继续支持这种编译模式。
2、部署预编译模式(Deployment pre-compilation)。这是ASP.NET 2.0的一个新特性,可以让你的工程在部署之前完全编译。使用完全编译,所有的code behind 文件、ASPX文件、HTML、图像资源、以及其他后台代码都根据程序的大小和编译环境,编译成一到多个可执行配件。这些配件包括所有用于网站的编译代码、资源文件和配置文件,都不可以修改。这个编译方法提供了最高的性能和最强的安全,但是以牺牲在部署后无法修改为代价。如果你致力于打造高度视觉化和高度安全的网站,这个时最后部署的最佳选择。但是,如果你正在你本地的intranet中建造一个小的站点,并且这个站点在不断改变,部署预编译模式将时致命的。
3、ASP.NET 2.0 编译模式也允许你对你的程序预编译所有的code behind文件,仍然能可以更新你的代码。你可以把你的code behind和原始.aspx 文件(都是部分类)编译成一个单独的预编译类(页面的基本类)。如果你选择在运行的时候编辑你的.aspx文件,你必须简单地重新编译你的页面。
4、完全运行时编译(Full runtime compilation)。在另外一个部署预编译的极端情况下,ASP.NET 2.0 提供一个新的机制在运行时编译整个程序。你可以将你的不编译code behind 文件和任何其他相关的代码放到一个新的\code目录下,让ASP.NET 2.0 新建和维持一些引用,指向在运行时从这些文件生成的配件。在改变网站内容方面,这个选择提供了最好的灵活性,代价在服务器就是存储不编译的代码。
选择最好的编译方式取决于你的环境和需求。但是,编译模式仍然易用。即使你选择使用\code目录来存储你的code behind文件,你可能仍然使用全编译方式部署你的程序。
批处理编译
在ASP.NET 2.0当中,你可以用单一URL请求批处理编译任何程序。使用ASP.NET 1.x,批处理编译去掉了第一次网页请求的延迟,但是创造一个更长的开始的时间循环。另外,批处理编译仍然要求code behind 文件在部署前编译。
Web.config的批处理编译设置在ASP.NET 2.0中仍然有效。批处理编译的优点就是对于第一个用户,页面能够立即执行,并且ASP文件中的任何错误都会在批处理编译时发现。但是,批处理编译在程序开始的时候会有点延迟,并且在Web.config文件建立。我们需要注意的是,如果一个文件失败了,批处理会报错。
部署预编译
部署与编译可以让你创建一到多个配件,这些配件都是你的网站的可执行版本。最后的配件包括网站的可编译代码。HTML页面,资源,配置文件和ASPX页面都要单独拷贝。部署预编译要求使用一个叫做aspnet_compiler.exe的命令行工具。这个工具创建了一个目标部署目录,包括有配件的/bin目录,各种ASPX页面的根文件。这个工具还可以用来做原状预编译,类似于我们叫做的“魔术页面”的动作。这些根文件共享你的ASPX文件的名称,但是包含简单代码来调用编译配件。换句话说,ASPX页面都是简单的空壳,而不是全功能的页面。

没有评论:
发表评论