19.6 ASP.NET页面事件
ASP.NET开发人员一直在服务器端代码中使用各种事件。他们使用的许多事件都与特定的服务器控件相关。例如,如果在终端用户单击Web页面上的 一个按钮时,要执行某个操作,就应在服务器端代码中创建一个按钮单击事件,如下所示:
< SPAN>
- Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles
- Button1.Click
- Label1.Text = TextBox1.Text
- End Sub
除了服务器控件之外,开发人员还可以在创建或删除ASP.NET页面时执行操作。ASP.NET页面总是为这些情况包含许多事件。下面列出了可以在 ASP.NET 1.0/1.1中使用的所有页面事件:
AbortTransaction
CommitTransaction
DataBinding
Disposed
Error
Init
Load
PreRender
Unload
这个列表中的一个常用页面事件是Load,它在VB中的用法如下(称为示例4,后面将引用它):
- Protected Sub Page_Load( ByVal sender As Object , ByVal e As System.EventArgs)
- Handles Me .Load
- Response.Write( "This is the Page_Load event" )
- End Sub
除了上面列出的页面事件之外,ASP.NET 3.5还添加了如下新事件。
InitComplete-- 指定完成了页面的初始化。
LoadComplete-- 指定页面已完全加载到内存中。
PreInit-- 指定在初始化页面之前的那一刻。
PreLoad-- 指定页面在加载到内存之前的那一刻。
PreRenderComplete-- 指定页面显示在浏览器之前的那一刻。
构建这些页面事件的方式与上面的页面事件完全相同。例如,PreInit事件的用法如下所示:
- <script runat= "server" language= "vb" >
- Protected Sub Page_PreInit( ByVal sender As Object , ByVal e As
- System.EventArgs)
- Page.Theme = Request.QueryString( "ThemeChange" )
- End Sub
- </script>
如果创建一个ASP.NET 3.5页面,打开跟踪功能,就可以看到主页面事件的发生顺序:
(1) PreInit
(2) Init
(3) InitComplete
(4) PreLoad
(5) Load
(6) LoadComplete
(7) PreRender
(8) PreRenderComplete
(9) Unload
增加了这些新选项之后,就可以在页面编译过程的许多不同地方处理页面和页面上的控件了。
19.7 ASP.NET应用程序文件夹
在创建ASP.NET应用程序时,ASP.NET 3.5会使用基于文件的方式。在应用程序中,可以添加任意多个文件和文件夹,且每次在解决方案中添加新文件时,都无须重新编译它们。ASP.NET 3.5可以自动、动态地预编译ASP.NET应用程序。
ASP.NET 1.0/1.1把解决方案中的所有对象都编译到一个DLL中。在ASP.NET 3.5中不一定如此,因为应用程序有一个定义好的文件夹结构。使用ASP.NET中定义好的文件夹,可以自动编译代码,在整个应用程序中访问应用程序主 题,在需要时使用全球化资源。下面就介绍这些文件夹。
19.7.1 /App_Code文件夹
/App_Code文件夹存储了类、.wsdl文件和类型化的数据集。存储在这个文件夹中的所有对象都自动应用于解决方案中的所有页面。 /App_Code文件夹的优点是,把某个对象放在其中时,Visual Studio 2008会自动检测到它,如果它是一个类(例如.vb文件),就编译它,自动创建XML Web服务代理类(在.wsdl文件中),或者在.xsd文件中自动创建类型化的数据集。
自动编译了文件后,这些对象就可以应用于同一个解决方案中的所有ASP.NET页面。下面看看如何通过/App_Code文件夹在解决方案中使用一 个简单的类。要创建/App_Code文件夹,可以右击解决方案,选择Add ASP.NET Folder | App_Code菜单项。注意Visual Studio 2008对待此文件夹的方式不同于解决方案中的其他文件夹。/App_Code文件夹用另一种颜色显示(灰色),在文件夹的图标旁边有一个文档图片,如图 19-9所示。
(点击查看大图)图 19-9 |
- Imports Microsoft.VisualBasic
- Public Class Calculator
- Public Function Add( ByVal a As Integer , ByVal b As Integer ) As Integer
- Return (a + b)
- End Function
- End Class
保存这个文件,它现在就可用于解决方案中的任意页面。为了演示这一点,创建一个简单的.aspx页面,它只包含一个标签服务器控件。下面的代码放在 Page_Load事件中,以使这个新类可用:
- <%@ Page Language= "VB" %>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
- "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" >
- <script runat= "server" >
- Protected Sub Page_Load( ByVal sender As Object , ByVal e As System.
- EventArgs)
- Dim myCalc As New Calculator
- Label1.Text = myCalc.Add(12, 12)
- End Sub
- </script>
运行这个.aspx页面,注意它可以使用Calculator类,在使用之前不需要编译它。实际上,在解决方案中保存了这个类,或把它移动 到/App_Code文件夹,就可以使用IntelliSense功能获得这个类上的方法了,如图19-10所示。
(点击查看大图)图 19-10 |
将Subtract方法添加到Calculator类中后,保存文件,返回.aspx页面。注意,现在类已经由 IDE重新编译了,新方法已经可以用于页面了,它可以在IntelliSense中看到,如图19-11所示。
- Imports Microsoft.VisualBasic
- Public Class Calculator
- Public Function Add( ByVal a As Integer , ByVal b As Integer ) As Integer
- Return (a + b)
- End Function
- Public Function Subtract( ByVal a As Integer , ByVal b As Integer ) As
- Integer
- Return (a - b)
- End Function
- End Class
(点击查看大图)图 19-11 |
放在/App_Code文件夹中的所有内容都编译到一个程序集中。放在/App_Code文件夹中的类文件不一定用某种特定的语言编写。例如,解决 方案的所有页面都用VB 2008编写,但该解决方案的/App_Code文件夹中的Calculator类可以用C#建立(Calculator.cs)。
包含在这个文件夹中的所有类都构建到一个程序集中,所以不能在根/App_Code文件夹中包含多种语言的类,如下所示:
- /App_Code
- Calculator.cs
- AdvancedMath.vb
如果/App_Code文件夹中有两个用不同语言编写的类(如上所示),就会抛出一个错误。不能让编译器处理两种不同的语言。因此,为了在 /App_Code文件夹中使用多种语言,必须修改文件夹结构和web.config文件。
首先,给/App_Code文件夹添加两个新的子文件夹/VB和/CS,这会得到如下文件夹结构:
- /App_Code
- /VB
- Add.vb
- /CS
- Subtract.cs
现在仍不能把这些类文件正确编译到各自的程序集中,因为还需要给web.config文件添加一些内容。现在解决方案中可能还没有 web.config文件,所以通过Solution Explorer添加该文件。之后,修改<compilation>节点,如下所示:
- <compilation>
- <codeSubDirectories>
- <add directoryName= "VB" ></add>
- <add directoryName= "CS" ></add>
- </codeSubDirectories>
- </compilation>
修改了web.config文件后,就可以在ASP.NET页面中使用各个类了。另外,放在CS文件夹中的C#类现在会自动编译,与放在VB文件夹 中的Visual Basic类一样。我们可以把这些目录添加到web.config文件中,所以不需要给它们命名为VB和CS,而可以给它们指定任意名称。
19.7.2 /App_Data文件夹
/App_Data文件夹包含应用程序使用的数据库,它很适合于集中存储应用程序可能使用的所有数据库。/App_Data文件夹可以包含 Microsoft SQL Express文件(.mdf文件)、Microsoft Access文件(.mdb文件)、XML文件等。
应用程序使用的用户账户可以读写/App_Data文件夹包含的所有文件。该账户默认为ASPNET。在这个文件夹中存储所有数据文件的另一个原因 是,许多ASP.NET系统都使用/App_Data文件夹,如成员和角色管理系统、ASP.NET MMC插件、新的IIS Manager和ASP.NET Web Site Administration Tool等GUI工具。
19.7.3 /App_Themes文件夹
主题是为站点上每个页面提供相同的外观和操作的一种新方法。要实现主题,应使用.skin文件、CSS文件和站点上服务器控件使用的图像。所有这些 元素都可以创建一个主题,它们存储在解决方案的/App_Themes文件夹中。这样,就可以确保解决方案中的所有页面都可以利用主题,将它的元素应用于 页面的控件和标记。
19.7.4 /App_GlobalResources文件夹
资源文件是一些字符串表。当应用程序需要根据文化改变其内容时,这些字符串表可以用作应用程序的数据字典。 在/App_GlobalResources文件夹中可以添加程序集资源文件(.resx),它们会动态编译,成为解决方案的一部分,供应用程序中的所 有.aspx文件使用。在使用ASP.NET 1.0/1.1时,必须使用resgen.exe工具,将资源文件编译为.dll或.exe,才能在解决方案中使用。而在ASP.NET 3.5中使用资源文件已经大大简化了,只需把应用程序资源放在这个文件夹中,就立即可以使用它们。
< SPAN>
19.7.5 /App_LocalResources文件夹
如果对使用/App_GlobalResources文件夹构建可在整个应用程序内使用的资源不感兴趣,可以让资源用于单个.aspx页面。为此, 只需使用/App_LocalResources文件夹。
要把页面专用的资源文件添加到/App_LocalResources文件夹中,只需以如下方式构建.resx文件名:
Default.aspx.resx
Default.aspx.fi.resx
Default.aspx.ja.resx
Default.aspx.en-gb.resx
在Default.aspx上使用的资源声明可以从/App_LocalResources文件夹的相应文件中检索。如果没有找到其他匹配,就默认 使用Default.aspx.resx资源文件。但如果客户在使用文化fi-FI(芬兰),就使用Default.aspx.fi.resx文件。
19.7.6 /App_WebReferences文件夹
/App_WebReferences文件夹是ASP.NET以前版本使用的Web References文件夹的新名称。使用/App_WebReferences文件夹,可以访问应用程序引用的远程Web服务。
19.7.6 /App_WebReferences文件夹
/App_WebReferences文件夹是ASP.NET以前版本使用的Web References文件夹的新名称。使用/App_WebReferences文件夹,可以访问应用程序引用的远程Web服务。
19.7.7 /App_Browsers文件夹
/App_Browsers文件夹包含.browser文件,.browser文件是XML文件,可以标识向应用程序发出请求的浏览器,并理解这些 浏览器的功能。在C:/Windows/Microsoft.NET/ Framework/v2.0.50727/CONFIG/Browsers中有一个可全局访问的.browser文件列表。另外,如果要修改这些默认的 浏览器定义文件,只需将Browsers文件夹中的对应.browser文件复制到应用程序的/App_Browsers文件夹,修改其定义即可。
19.8 Global.asax
在ASP.NET应用程序中添加新项时,会打开Add New Item对话框。在这个对话框中可以把Global Application Class添加到应用程序中。这会添加一个Global.asax文件。这个文件由应用程序用于保存应用程序级别的事件、对象和变量-- 这些都可以在整个应用程序的范围内访问。ASP开发人员有类似的Global.asa文件。
ASP.NET应用程序只能有一个Global.asax文件,它支持许多项。创建它时,会得到如下模板:
- <%@ Application Language= "VB" %>
- <script runat= "server" >
- Sub Application_Start( ByVal sender As Object , ByVal e As EventArgs)
- ' Code that runs on application startup
- End Sub
- Sub Application_End( ByVal sender As Object , ByVal e As EventArgs)
- ' Code that runs on application shutdown
- End Sub
- Sub Application_Error( ByVal sender As Object , ByVal e As EventArgs)
- ' Code that runs when an unhandled error occurs
- End Sub
- Sub Session_Start( ByVal sender As Object , ByVal e As EventArgs)
- ' Code that runs when a new session is started
- End Sub
- Sub Session_End( ByVal sender As Object , ByVal e As EventArgs)
- ' Code that runs when a session ends.
- ' Note: The Session_End event is raised only when the sessionstate
- ' mode is set to InProc in the Web.config file. If session mode is
- ' set to StateServer
- ' or SQLServer, the event is not raised.
- End Sub
- </script>
在.aspx页面中可以使用页面级别的事件,同样,在Global.asax文件中也可以使用所有的应用程序事件,除了上述代码示例列出的事件之 外,在这个文件中还可以构建如下事件:
Application_Start-- 在应用程序接收到第一个请求时调用。这个事件适合在应用程序中指定应用程序级别的变量或必须给所有用户维护的状态。
Session_Start-- 类似于Application_Start事件,但这个事件在某个用户第一次访问应用程序时引发。例如,Application_Start事件在第一个 请求进入时引发,这会启动应用程序;而Session_Start在每个终端用户第一次从应用程序中请求信息时调用。
Application_BeginRequest-- 这个事件没有列在Visual Studio 2008提供的上述模板中,它在每个请求发出之前引发。这表示,当一个请求进入服务器时,Application_ BeginRequest会在处理它之前引发,执行处理该请求之前的任务。
Application_AuthenticateRequest-- 每个请求都会引发这个事件,以设置请求的定制身份验证。
Application_Error-- 应用程序的用户在应用程序的任意位置抛出一个错误时引发该事件。它适合于提供应用程序级别的错误处理或把错误记录到服务器的事件日志中。
Session_End-- 运行在InProc模式下时,这个事件在终端用户退出应用程序时引发。
Application_End-- 应用程序结束时引发该事件。大多数ASP.NET开发人员都不常用这个事件,因为ASP.NET可以关闭并清除不再使用的对象。
除了Global.asax文件允许访问的全局应用程序事件之外,还可以在该文件中使用下面的指令,这与其他ASP.NET页面相同:
@Application
@Assembly
@Import
这些指令的执行方式与它们用于其他ASP.NET页面类型时相同。下面的代码是使用Global.asax文件的一个例子,它演示了如何记录 ASP.NET应用程序域何时停止。此时,ASP.NET应用程序会突然停止,所以应将记录代码放在Global.asax文件的 Application_End方法中:
- <%@ Application Language= "VB" %>
- <%@ Import Namespace = "System.Reflection" %>
- <%@ Import Namespace = "System.Diagnostics" %>
- <script runat= "server" >
- Sub Application_End( ByVal sender As Object , ByVal e As EventArgs)
- Dim MyRuntime As HttpRuntime = _
- GetType (System.Web.HttpRuntime).InvokeMember( "_theRuntime" , _
- BindingFlags.NonPublic Or BindingFlags. Static Or _
- BindingFlags.GetField, _
- Nothing , Nothing , Nothing )
- If (MyRuntime Is Nothing ) Then
- Return
- End If
- Dim shutDownMessage As String = _
- CType (MyRuntime. GetType ().InvokeMember( "_shutDownMessage" , _
- BindingFlags.NonPublic Or BindingFlags.Instance Or
- BindingFlags.GetField, _
- Nothing , MyRuntime, Nothing ), System. String )
- Dim shutDownStack As String = _
- CType (MyRuntime. GetType ().InvokeMember( "_shutDownStack" , _
- BindingFlags.NonPublic Or BindingFlags.Instance Or
- BindingFlags.GetField, _
- Nothing , MyRuntime, Nothing ), System. String )
- If ( Not EventLog.SourceExists( ".NET Runtime" )) Then
- EventLog.CreateEventSource( ".NET Runtime" , "Application" )
- End If
- Dim logEntry As EventLog = New EventLog()
- logEntry.Source = ".NET Runtime"
- logEntry.WriteEntry( String .Format(_
- "shutDownMessage={0}/r/n/r/n_shutDownStack={1}" , _
- shutDownMessage, shutDownStack), EventLogEntryType. Error )
- End Sub
- </script>
把这些代码放在Global.asax文件中后,启动ASP.NET应用程序。接着,执行某个操作,以重新启动应用程序。例如在运行应用程序时修改 web.config文件。这会引发Application_End事件,事件日志如图19-12所示。
(点击查看大图)图 19-12 |