代码改变世界

浅谈ASP.NET网站的编译模型和参数

2011-10-26 17:13  Ivony...  阅读(2467)  评论(3编辑  收藏  举报

在发布一个网站(WebSite而不是WebProject)时,我们会看到这样一个对话框:

image

红框中的三个选项,你知道他们的具体含义和对最终发布结果的影响么?OK,如果您已然明了,这篇文章您可以忽略了,如果直到今天您还是一知半解的话,希望这篇文章对您有所帮助。

 

页面类和代码类

从ASP.NET第一个版本,就引入了CodeBehind的概念,我们既可以像ASP那样,将页面的处理代码直接放在aspx中,也可以放在另一个独立的代码文件中,通过aspx文件中的@Page指令的CodeBehind属性关联起来。到了ASP.NET 2.0时代,这一项技术进化的更为成熟。在网站项目中,使用@Page指令的CodeFile指示页面的处理代码文件,并使用Inherits属性令页面类继承于代码隐藏文件中所定义的类型。其实一个具备完整的Test.aspx和Test.aspx.cs两个文件的页面,至少存在两个类型的定义和三个代码文件。

第一个类型是从Test.aspx所编译出来的页面类,这个类一般放在ASP命名空间下,即ASP.Test(所以ASP命名空间在网站中不能乱用)。这个类型对应一个代码文件,在ASP.NET网站编译和发布时,这个代码文件会被临时的创建出来,当编译和发布完成后旋即被删除。

另一个类型是在Test.aspx.cs文件中所定义的类型,默认情况下这个类型名称是Test且没有命名空间。这个类型有两个代码文件,其一是从aspx文件分析出来的控件声明(用于声明在aspx中有ID且不在模版控件中的控件为字段,使得在aspx.cs文件中可以直接通过ID访问当这些控件)代码文件,在ASP.NET 1.x时代,这些代码是直接由IDE环境产生在Test.aspx.cs文件中的,从ASP.NET 2.0开始产生独立的代码文件并声明为partial,与Testaspx.cs中的另一部分声明合并为另一个类型Test。为了接下来的阐述方便,下文将这个类型称之为代码类。

事实上从ASP.NET第一个版本到现在的版本,只要你使用了代码分离模型,就一定会产生两个类型而不是一个。ASP.NET 2.0引入partial只是为了将控件声明代码从aspx.cs文件中剥离,而并没有改变根本的两个类型的模型。同时,这里所阐述的aspx文件的类型模型,同样也适用于asmx、ashx、asax等文件。

页面类总是继承于代码类,除非代码类不存在,此时,页面类从适合的基类(Page、UserControl或是HttpApplication)继承。

顺带值得一提的是,事实上代码类不局限于必须是aspx.cs中定义,只要是aspx文件代码中能访问到的任何类型(譬如网站引用的某个程序集中所定义的类型或是App_Code中定义的类型)都可以作为代码类,但这已经超出了本文的范畴,在此不做深究。

其实罗嗦了半天,主要就是分清楚两个类型,页面类和代码类,只有理解了这两个类型的区别,才能完全理解上面的编译设置。

允许更新此预编译站点

简单的说这个选项就是控制是否在发布时是否预编译页面类,若不勾选则预编译页面类,勾选则不预编译,待到页面第一次被访问时才进行编译。特别需要注意的是,不勾选此选项才表示预编译页面类,勾选反而会导致页面类延后编译。

如果勾选此选项,则页面类不会被编译成DLL,这样发布后仍然可以修改aspx、asmx、ashx、asax等文件,这才是“允许更新此预编译站点”的真实含义。事实上这个英文更准确的翻译应该是“允许修改预编译后的页面文件”。

若没有勾选此选项,则正式发布后的aspx、ashx、asmx、asax文件都将是任何实质内容的壳文件,其存在的意义只是为了IIS不报404错误。

使用固定命名和单页程序集

这个选项很大程度上决定了编译后网站bin文件夹中DLL的数量,若勾选这个选项,则每一个页面都会被编译成独立的程序集(DLL),DLL的名称一般是App_Web_{页面文件的名称}.{页面虚拟路径的HASH}.dll,如App_Web_Test.aspx.12345678.dll。

如果使用了代码分离模型,并且没有勾选“允许更新此预编译站点”这个选项,则这个文件里面至少包含两个类型,页面类和代码类。若勾选了“允许更新此预编译站点”这个选项,则页面类不会在DLL中。

若不勾选此选项,则ASP.NET编译工具将尝试将所有的类型打包到一个程序集中。

注意,即使不勾选此选项,最终所有的页面都打包到一个程序集中,在网站项目中,不同的页面之间也是不能自由互访的(WebProject可以)。如果我要在Test.aspx或是Test.aspx.cs中访问Index.aspx.cs中定义的类型Index,即使最终所有的代码都会编译到一个程序集,但仍需要使用@Reference指令。

此选项的主要用途在于增量更新,使用固定命名和单页程序集可以使得我们修改了某个页面后,只需要更新线上环境这个页面所对应的DLL即可,而不必更新整个网站。

发出调试信息

这个选项简单的说就是是否为编译的DLL创建pdb文件,pdb文件可以在出现异常时给出源代码相关的信息,一般来说就是行号和相关源代码,像下面这样:

image

而对于没有pdb文件的程序集,则在异常信息中显示为这样:

image