global.asax是一個文本文件,它提供全局可用代碼。這些代碼包括應用程序的事件處理程序以及會話事件、方法和靜態變量。有時該文件也被稱為應用程序文件。
global.asax 文件中的任何代碼都是它所在的應用程序的一部分。每個應用程序在其根目錄下只能有一個global.asax文件。然而,這個文件是可選的。如果沒有global.asax文件,應用程序將對所有事件應用由 HttpApplication類提供的默認行為。
提示:經典ASP有一個與global.asax類似格式和構造的,名為global.asa的文件。實際上,如果將一個正在運行的global.asa文件代碼復制到global.asax中,應用程序同樣可以運行。
global.asax 文件中的任何代碼都是它所在的應用程序的一部分。每個應用程序在其根目錄下只能有一個global.asax文件。然而,這個文件是可選的。如果沒有global.asax文件,應用程序將對所有事件應用由 HttpApplication類提供的默認行為。
提示:經典ASP有一個與global.asax類似格式和構造的,名為global.asa的文件。實際上,如果將一個正在運行的global.asa文件代碼復制到global.asax中,應用程序同樣可以運行。
Global.asax 文件(也稱作 ASP.NET 應用程序文件)是可選文件,包含用於響應 ASP.NET 或 HttpModule 引發的應用程序級別事件的代碼。Global.asax 文件駐留在基於 ASP.NET 的應用程序的根目錄中。在運行時,分析 Global.asax 文件並將其編譯到一個動態生成的 .NET Framework 類,該類是從 HttpApplication 基類派生的。Global.asax 文件本身被配置為自動拒絕對它的任何直接 URL 請求;外部用戶無法下載或查看在該文件中編寫的代碼。
ASP.NET Global.asax 文件能夠與 ASP Global.asax 文件共存。您可以在 WYSIWYG 設計器中或“記事本”中創建 Global.asax 文件,或者將它創建為編譯的類並將該類作為程序集部署在應用程序的 \Bin 目錄中。但是,在后面的一種情況中,您仍需要一個引用該程序集的 Global.asax 文件。
Global.asax 文件是可選的。如果不定義該文件,ASP.NET 頁框架假設您未定義任何應用程序或會話事件處理程序。
當您將更改保存到活動 Global.asax 文件時,ASP.NET 頁框架檢測到該文件已被更改。它完成應用程序的所有當前請求,將 Application_OnEnd 事件發送到任何偵聽器,並重新啟動應用程序域。實際上,這會重新啟動應用程序,關閉所有瀏覽器會話並刷新所有狀態信息。當來自瀏覽器的下一個傳入請求到達時,ASP.NET 頁框架將重新分析並重新編譯 Global.asax 文件並引發 Application_OnStart 事件。
和原理的ASP差不多,但功能更加強勁.
當應用程序運行的時候,global.asax的內容被編譯到一個繼承自HttpApplication類的類中。因此,HttpApplication類中所有的方法、類和對象對於應用程序都是可用的。
CLR 監控着global.asax的變化。如果它察覺到這個文件發生了改變,那么將自動啟動一個新的應用程序復本,同時創建一個新的應用程序域。原應用程序域當前正在處理的請求被允許結束,而任何新的請求都交由新應用程序域來處理。當原應用程序域的最后一個請求處理完成時,這個應用程序域即被清除。這有效的保證了應用程序可以重新啟動,而不被任何用戶察覺。
為防止應用程序用戶下載應用程序而看到源代碼,ASP.NET缺省配置為阻止用戶查看global.asax的內容。如果有人在瀏覽器輸入以下URL:
http://localhost/progaspnet/Global.asax
這將會收到一個403(禁止訪問)錯誤信息或者類似的信息如:
This type of page is not served。
提示:簡單而言,web.config文件與global.asax有些類似的地方。如果這個文件被更改,應用程序將自動“重啟”。同樣,也不可能在瀏覽器中查看web.config文件。
Global.asax文件從外觀和結構上與頁面文件(.aspx)相似。它可以有一個或多個部分,簡要描述如下:
l 指令
l 腳本塊
l Object聲明
正如Web頁和Web服務能夠使用代碼隱藏功能,global.asax同樣也可以。然而,與Web頁和Web服務的條件有所不同,VS2005默認狀態下不對global.asax使用代碼隱藏功能。
提示:Visual Studio 2005預覽版默認對global.asax使用代碼隱藏模型。目前仍然支持代碼隱藏,但不是默認使用。
為了對global.asax使用代碼隱藏技術,可使用位於該文件頭部的Application指令(類似於頁面文件的Page指令,下一節將詳細介紹)的Inherits屬性,該屬性指向global.asax.cs中的代碼隱藏類。
同時,也有一個CodeBehind屬性用來指向代碼隱藏文件。然而,如果它指向的是一個位於App_Code文件夾以外的位置,那么必須對這個類文件進行手動編輯。
通過右鍵單擊解決方案資源管理器中的網站或者單擊網站菜單,然后選擇“Add New Item...”,接着選擇全局應用程序類,可以為Web應用程序添加一個global.asax文件。保留默認名稱global.asax。
VS2005將創建一個如示例18-1所列的文件。模板中包括對以下5個事件的空白聲明:Application_Start、Application_End、Session_Start、Session_End和Applica- tion_Error。
示例18-1:global.asax模板
<%@ Application Language="C#" %>
在示例18-2所列舉的global.asax文件中,為應用程序狀態設置了一些值,同時,在每次應用程序啟動的時候向日志文件寫一個條目。為了使用這個示例,需要保證ASP.NET帳戶對根目錄c:\具有寫入權限(在產品系統中不推薦)。
示例18-2:global.asax示例
<%@ Application Language="C#"%>
指令
與Web頁和Web服務文件相比,global.asax可以以多個指令作為開始。這些指令在處理ASP.NET文件時指定應用程序編譯的設置。與Page指令相比,Application指令可
接受一個或者多個具有字典結構的屬性/值對。此處支持三個指令:Application、Import和Assembly。
Application Application指令設置編譯器的應用程序專用屬性。以下是一個Application指令示例:
<%@ Application Language="C#" Inherits="WebServiceConsumer.Global"
Description="A sample application" %>
Language 屬性可以設置為任何一種標准語言名稱:VB、C#、JS、或VJ#,它們分別對應VB2005、C#、JScript.NET或J#。(可以使用任何一種支持.NET平台的第三方語言)默認值為C#。此處的Language設置的是語言專門用於global.asax文件,而非其他應用程序代碼文件。例如,可以完全合法地在global.asax文件中使用C#,在.aspx文件中使用VB2005,相反亦然。
Inherits屬性指定所繼承類名,具有代表性的如代碼隱藏文件中的類。
Description屬性接受對應用程序的文本描述,而分析器和編譯器將會忽略它。
CodeBehind屬性在Visual Studio .NET(非VS2005)中用來指定包含的代碼隱藏文件。
Import Import指令僅包括一個Namespace屬性。所指定名字空間被明確地導入應用程序中,使其所有的類和接口都可用。導入的名字空間可以是.NET Framework的一部分或者用戶自定義的名字空間。
以下是一個典型的Import指令:
<%@ Import Namespace="System.Data" %>
只能有一個Namespace屬性。如果需要導入多個名字空間,那么需要使用多個Import指令。
下列名字空間自動導入到所有的Web應用程序中,所以沒必要使用Import指令。
l System
l System.Collections
l System.Collections.Specialized
l System.Configuration
l System.IO
l System.Text
l System.Text.RegularExpressions
l System.Web
l System.Web.Caching
l System.Web.Security
l System.Web.SessionState
l System.Web.UI
l System.Web.UI.HtmlControls
l System.Web.UI.WebControls
Assembly Assembly指令用於在編譯過程中將一個程序集鏈接到當前應用程序。這樣可以使所有程序集的類與接口對應用程序都是可用的。
提示:典型的程序集是.dll或.exe文件,這將在下一章中詳細講解。
由於在編譯時引用程序集,所以可以使用Assembly指令綁定程序集,然后在運行時將其加載到應用程序池中。
位於應用程序集緩存(也就是位於bin目錄和App_Code目錄中的代碼文件)中的程序集可自動連接到應用程序。因此,任何位於bin目錄的程序集,或者由App_Code目錄中的代碼編譯而來的任何程序集,都不需要使用Assembly指令實現連接。
Assembly指令包括兩個屬性:Name和Src。Name屬性是一個字符串,表示連接到應用程序的程序集名字,它不能包含路徑。Src屬性則是指向源文件的路徑(只能為相對路徑),這些文件將被動態編譯和連接。
每個程序集指令只能有一個屬性。如果需要連接多個程序集,則應使用多個Assembly指令。
Assembly指令類似於:
<%@ Assembly %>
<%@ Assembly Src="sources/SomeSourceFile.cs" %>
腳本塊
典型的global.asax文件中包含大量代碼,這些代碼包含在以script標簽起止的腳本塊中:
如果使用代碼隱藏,雖然代碼隱藏文件中的代碼本身沒有附加script標簽,但包含在代碼隱藏文件中的代碼與腳本塊中的代碼是等效的。
腳本塊中的代碼可以包含事件處理程序或者方法,下文將對此進行講解。
事件
如同Web頁和控件可以公開事件一樣,應用程序中的Application對象和 Session對象也能夠公開事件。這些事件能被global.asax文件或指定的文件中的事件處理程序處理。例如,當應用程序開始執行時,觸發 Application_Start事件;當應用程序結束時,觸發Application_End事件。Application的某些事件是每當頁面請求時觸發,而其他一些事件,例如Application_Error,則僅在特定情況下觸發。
示例18-2中的global.asax文件代碼說明了Application_Start 和Application_End事件。示例18-2中的Application_Start事件設置了兩個Application屬性:一個是名為 strConnectionString的字符串,一個是名為arBooks的字符串數組。事件處理程序方法調用一個名為WriteFile的輔助方法,它包含在global.asax文件中。該輔助方法將一個字符串寫入日志文件中。以下是示例18-2中的WriteFile方法代碼:
void WriteFile(string strText)
{
System.IO.StreamWriter writer =
new System.IO.StreamWriter(@"C:\test.txt",true);
string str;
str = DateTime.Now.ToString( ) + " " + strText;
writer.WriteLine(str);
writer.Close( );
}
WriteFile 是一個簡單的記錄日志的方法。該方法初始化一個基於文本文件的 StreamWriter對象,並對c:\test.txt進行硬編碼。它在文件中添加了一個時間戳,並寫入通過方法傳遞的字符串。 StreamWriter方法的布爾值參數為true,其表示如果文件已經存在,那么將文本行追加到文件中。如果文件不存在,則創建一個文件。
Application_End事件處理方法調用了另一個WriteFile方法,它添加了一個日志條目以記錄應用程序結束。
為了查看這兩個事件處理程序的結果,可對global.asax進行一些無意義的編輯,並保存文件。此時將強制結束應用程序。然后請求虛擬目錄中的任意URL地址。例如,使用上一章中的一個網頁——實際上無論哪一個——或者一個自己創建的網頁。示例18-3顯示了日志文件內容。
示例18-3:Test.txt摘錄
8/26/2006 5:46:23 PM Application Starting
8/26/2006 6:13:35 PM Application Ending
8/27/2006 10:17:39 PM Application Starting
8/27/2006 10:18:23 PM Application Ending
8/27/2006 10:18:36 PM Application Starting
如同Application對象的Start和End事件一樣,Session對象也擁有Session_ Start和Session_End事件。這將允許應用程序每次啟動和結束過程中為每個會話都運行代碼。
如示例18-4中高亮顯示的方法名所示,其包括了global.asax文件中所有可能的應用程序事件處理程序。在頁面請求被接受、處理和呈現過程中,可以容易地查看應用程序生命周期。
示例18-4:Global.asax事件說明
<%@ Application Language="C#" %>
以下是頁面請求觸發的所有事件,以觸發順序排序:
Application_BeginRequest
當ASP.NET開始處理每個請求時觸發。在這個事件處理中的代碼將在頁面或者服務處理請求之前執行。
Application_AuthenticateRequest
在驗證請求之前觸發。(正如第12章介紹的,驗證是確認用戶就是他所說的那個人的過程)在這個事件處理程序的代碼中允許實現自定義安全管道。
Application_AuthorizeRequest
在為請求授權之前觸發。(授權是確定是否請求用戶具有訪問資源的權限的過程,在
第12章已經介紹過)在這個事件處理程序的代碼中允許實現自定義安全管道。
Application_ResolveRequestCache
在ASP.NET確定是否應該生成新的輸出,或者由緩存填充前觸發。無論何種情況,都將執行該事件處理程序中的代碼。
Application_AcquireRequestState
在獲取會話狀態之前執行。
Application_PreRequestHandlerExecute
在將請求發送到服務於請求的處理程序對象之前觸發。當事件觸發后,頁面將由HTTP處理程序處理請求。
Application_PostRequestHandlerExecute
當HTTP處理程序與頁面請求一起完成時觸發。此時,Response對象將獲得由客戶端返回的數據。
Application_ReleaseRequestState
當釋放和更新試圖狀態時觸發。
Application_UpdateRequestCache
如果輸出被緩存,那么緩存更新時將觸發。
Application_EndRequest
當請求結束時執行。
Application_PreSendRequestHeaders
在向客戶端發送HTTP頭之前觸發。如果啟用響應緩存,這意味着直到所有數據都准備好(默認條件),都不會發送任何數據。該事件總是在Application_EndRequest事件之后。如果禁用響應緩存,那么無論何時將數據發送給客戶端,都將觸發該事件。響應控制由Page指令的一個屬性,或者Web服務的WebMethod屬性控制。
Application_PreSendRequestContent
向客戶端發送HTTP內容之前觸發。和Application_PreSendRequestHeaders事件一樣,Application_PreSendRequestContent事件能否被觸發取決於響應緩存是否可用。
以下列舉應用程序事件,它們在特定條件下觸發:
Application_Start
當應用程序啟動時觸發。當首次請求應用程序虛擬目錄中的任何頁面時,將啟動應用程序,同時如果應用程序已經運行,則不觸發該事件。
Application_End
應用程序結束時觸發。無論何時修改了配置文件(global.asax、global.asax.cs、
global.asax.vb或者web.config),或者服務器崩潰或者重啟,應用程序都將結束。通常在該事件處理程序中執行清除功能的代碼,例如關閉數據庫連接。
Session_Start
每個會話開始時觸發,這是放置具體會話代碼的地方。
Session_End
會話結束時觸發。它為保存存儲在會話中的任何數據提供了機會。
Application_Disposed
當CLR從內存中移除應用程序時觸發。
Application_Error
無論在應用程序中何時何處發生未處理的錯誤都將觸發。它提供了一個實現通用應用程序錯誤處理的好機會。
使用try...catch語句塊能夠在代碼中處理特定錯誤,也可以使用Page指令的ErrorPage屬性來捕獲頁面級錯誤。使用這些方式處理任何錯誤都不會觸發Application_Error事件。
為了測試新版的global.asax,在示例18-5中創建一個網頁。查看GlobalEvents站點。當該網頁運行時,將看到如圖18-4所示的頁面。
示例18-5:GlobalEvents網站的default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" %>
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
Global Events
Text="End Session"
OnClick="btnEndSession_Click" />
Text="Generate Error"
OnClick="btnError_Click" />
圖18-4:GlobalEvents
如圖18-4所示,可看到觸發了一系列應用程序事件。在這些事件執行的中途,呈現了.aspx頁面自身,接着是另一些應用程序事件。
警告:示例GlobalEvents必須在一個真實的IIS虛擬路徑下才能良好運行。
頁面第一次顯示時觸發Session_Start事件,而在隨后的顯示中則不再觸發該事件。 這是因為請求是相同的會話。單擊“End Session”按鈕,調用Session.Abandon方法,這將結束當前會話。下一次頁面被提交到服務器時,將再次觸發Session_Start 事件。
Post按鈕提供了一個簡單的再次提交頁面的方法。
示例18-4中大部分的應用程序事件處理程序都使用了Response.Write方法,以便顯示觸發的事件。然而,Application_Start和Application_End方法調用了WriteFile方法。如果在這些事件處理程序中試圖使用Response.Write方法,那么在頁面中將不會
顯示。因為那時用於呈現的頁面會話還沒有運行。但是,當檢查日志文件c:\test.txt時,將看到應用程序啟動和結束所顯示的條目。
示例18-4所示的global.asax文件說明了一種使用Application_Error事件的方法。以下列舉了這些代碼:
protected void Application_Error(Object sender, EventArgs e)
{
string strError;
strError = Server.GetLastError( ).ToString( );
if (Context!= null)
Context.ClearError( );
Response.Write("Application_Error" + "
");
Response.Write("Error Msg: " + strError + "
" +
"End Error Msg
");
}
該事件處理程序使用HttpServerUtility對象的GetLastError方法,以報告最后出現的錯誤。這個錯誤被轉換為一個字符串,並被指定給一個字符串變量:
strError = Server.GetLastError( ).ToString( )
接下來調用HttpContext對象的ClearError方法來清除目前HTTP請求中的所有錯誤:
Context.ClearError( )
如果沒有將錯誤清除,那么錯誤將顯示在客戶端瀏覽器,並且還是無法看見Respons- e.Write方法的顯示結果。
最后,Response.Write方法顯示一個信息,當前的錯誤將顯示在客戶端。
另一種向用戶報告錯誤的方式是顯示自定義錯誤處理頁面。為此,需要使用以下代碼行替代Application_Error事件處理程序中的Response.Write方法:
Response.Redirect("CustomErrorPage.aspx?Msg=" +
Server.UrlEncode(strError));
以上代碼行調用HttpServerUtility對象的UrlEncode方法,其將錯誤信息作為一個QueryString參數傳遞給CustomErrorPage.aspx頁面中的自定義錯誤處理代碼。 CustomErrorPage.aspx頁面有一個名為lblMessage的Label控件。以下是頁面中的Page_Load方法代碼:
void Page_Load(Object Source, EventArgs E)
{
lblMessage.Text = Request.QueryString["Msg"];
}
Default.aspx中的Generate Error按鈕故意觸發一個錯誤,以便查看錯誤處理。該按鈕的單擊事件處理程序的代碼如下所示,它將除零異常:
protected void btnError_Click(object sender, EventArgs e)
{
int a = 5;
int b = 0;
int c;
c = a / b;
}
服務器端包括
使用服務器端包括能夠實現在應用程序中包含外部源代碼文件。在編譯之前,包括文件中的代碼將被添加到global.asax文件中。盡管應用程序的語言可能與包括文件的語言不同,但是用於包括文件的語言必須與global.asax文件所使用的語言匹配。
下面是用於服務器端的語法:
在這個句法中,PathType類型可以是表18-1所示之一。
表18-1 PathType屬性
ASP.NET Global.asax 文件能夠與 ASP Global.asax 文件共存。您可以在 WYSIWYG 設計器中或“記事本”中創建 Global.asax 文件,或者將它創建為編譯的類並將該類作為程序集部署在應用程序的 \Bin 目錄中。但是,在后面的一種情況中,您仍需要一個引用該程序集的 Global.asax 文件。
Global.asax 文件是可選的。如果不定義該文件,ASP.NET 頁框架假設您未定義任何應用程序或會話事件處理程序。
當您將更改保存到活動 Global.asax 文件時,ASP.NET 頁框架檢測到該文件已被更改。它完成應用程序的所有當前請求,將 Application_OnEnd 事件發送到任何偵聽器,並重新啟動應用程序域。實際上,這會重新啟動應用程序,關閉所有瀏覽器會話並刷新所有狀態信息。當來自瀏覽器的下一個傳入請求到達時,ASP.NET 頁框架將重新分析並重新編譯 Global.asax 文件並引發 Application_OnStart 事件。
和原理的ASP差不多,但功能更加強勁.
當應用程序運行的時候,global.asax的內容被編譯到一個繼承自HttpApplication類的類中。因此,HttpApplication類中所有的方法、類和對象對於應用程序都是可用的。
CLR 監控着global.asax的變化。如果它察覺到這個文件發生了改變,那么將自動啟動一個新的應用程序復本,同時創建一個新的應用程序域。原應用程序域當前正在處理的請求被允許結束,而任何新的請求都交由新應用程序域來處理。當原應用程序域的最后一個請求處理完成時,這個應用程序域即被清除。這有效的保證了應用程序可以重新啟動,而不被任何用戶察覺。
為防止應用程序用戶下載應用程序而看到源代碼,ASP.NET缺省配置為阻止用戶查看global.asax的內容。如果有人在瀏覽器輸入以下URL:
http://localhost/progaspnet/Global.asax
這將會收到一個403(禁止訪問)錯誤信息或者類似的信息如:
This type of page is not served。
提示:簡單而言,web.config文件與global.asax有些類似的地方。如果這個文件被更改,應用程序將自動“重啟”。同樣,也不可能在瀏覽器中查看web.config文件。
Global.asax文件從外觀和結構上與頁面文件(.aspx)相似。它可以有一個或多個部分,簡要描述如下:
l 指令
l 腳本塊
l Object聲明
正如Web頁和Web服務能夠使用代碼隱藏功能,global.asax同樣也可以。然而,與Web頁和Web服務的條件有所不同,VS2005默認狀態下不對global.asax使用代碼隱藏功能。
提示:Visual Studio 2005預覽版默認對global.asax使用代碼隱藏模型。目前仍然支持代碼隱藏,但不是默認使用。
為了對global.asax使用代碼隱藏技術,可使用位於該文件頭部的Application指令(類似於頁面文件的Page指令,下一節將詳細介紹)的Inherits屬性,該屬性指向global.asax.cs中的代碼隱藏類。
同時,也有一個CodeBehind屬性用來指向代碼隱藏文件。然而,如果它指向的是一個位於App_Code文件夾以外的位置,那么必須對這個類文件進行手動編輯。
通過右鍵單擊解決方案資源管理器中的網站或者單擊網站菜單,然后選擇“Add New Item...”,接着選擇全局應用程序類,可以為Web應用程序添加一個global.asax文件。保留默認名稱global.asax。
VS2005將創建一個如示例18-1所列的文件。模板中包括對以下5個事件的空白聲明:Application_Start、Application_End、Session_Start、Session_End和Applica- tion_Error。
示例18-1:global.asax模板
<%@ Application Language="C#" %>
在示例18-2所列舉的global.asax文件中,為應用程序狀態設置了一些值,同時,在每次應用程序啟動的時候向日志文件寫一個條目。為了使用這個示例,需要保證ASP.NET帳戶對根目錄c:\具有寫入權限(在產品系統中不推薦)。
示例18-2:global.asax示例
<%@ Application Language="C#"%>
指令
與Web頁和Web服務文件相比,global.asax可以以多個指令作為開始。這些指令在處理ASP.NET文件時指定應用程序編譯的設置。與Page指令相比,Application指令可
接受一個或者多個具有字典結構的屬性/值對。此處支持三個指令:Application、Import和Assembly。
Application Application指令設置編譯器的應用程序專用屬性。以下是一個Application指令示例:
<%@ Application Language="C#" Inherits="WebServiceConsumer.Global"
Description="A sample application" %>
Language 屬性可以設置為任何一種標准語言名稱:VB、C#、JS、或VJ#,它們分別對應VB2005、C#、JScript.NET或J#。(可以使用任何一種支持.NET平台的第三方語言)默認值為C#。此處的Language設置的是語言專門用於global.asax文件,而非其他應用程序代碼文件。例如,可以完全合法地在global.asax文件中使用C#,在.aspx文件中使用VB2005,相反亦然。
Inherits屬性指定所繼承類名,具有代表性的如代碼隱藏文件中的類。
Description屬性接受對應用程序的文本描述,而分析器和編譯器將會忽略它。
CodeBehind屬性在Visual Studio .NET(非VS2005)中用來指定包含的代碼隱藏文件。
Import Import指令僅包括一個Namespace屬性。所指定名字空間被明確地導入應用程序中,使其所有的類和接口都可用。導入的名字空間可以是.NET Framework的一部分或者用戶自定義的名字空間。
以下是一個典型的Import指令:
<%@ Import Namespace="System.Data" %>
只能有一個Namespace屬性。如果需要導入多個名字空間,那么需要使用多個Import指令。
下列名字空間自動導入到所有的Web應用程序中,所以沒必要使用Import指令。
l System
l System.Collections
l System.Collections.Specialized
l System.Configuration
l System.IO
l System.Text
l System.Text.RegularExpressions
l System.Web
l System.Web.Caching
l System.Web.Security
l System.Web.SessionState
l System.Web.UI
l System.Web.UI.HtmlControls
l System.Web.UI.WebControls
Assembly Assembly指令用於在編譯過程中將一個程序集鏈接到當前應用程序。這樣可以使所有程序集的類與接口對應用程序都是可用的。
提示:典型的程序集是.dll或.exe文件,這將在下一章中詳細講解。
由於在編譯時引用程序集,所以可以使用Assembly指令綁定程序集,然后在運行時將其加載到應用程序池中。
位於應用程序集緩存(也就是位於bin目錄和App_Code目錄中的代碼文件)中的程序集可自動連接到應用程序。因此,任何位於bin目錄的程序集,或者由App_Code目錄中的代碼編譯而來的任何程序集,都不需要使用Assembly指令實現連接。
Assembly指令包括兩個屬性:Name和Src。Name屬性是一個字符串,表示連接到應用程序的程序集名字,它不能包含路徑。Src屬性則是指向源文件的路徑(只能為相對路徑),這些文件將被動態編譯和連接。
每個程序集指令只能有一個屬性。如果需要連接多個程序集,則應使用多個Assembly指令。
Assembly指令類似於:
<%@ Assembly %>
<%@ Assembly Src="sources/SomeSourceFile.cs" %>
腳本塊
典型的global.asax文件中包含大量代碼,這些代碼包含在以script標簽起止的腳本塊中:
如果使用代碼隱藏,雖然代碼隱藏文件中的代碼本身沒有附加script標簽,但包含在代碼隱藏文件中的代碼與腳本塊中的代碼是等效的。
腳本塊中的代碼可以包含事件處理程序或者方法,下文將對此進行講解。
事件
如同Web頁和控件可以公開事件一樣,應用程序中的Application對象和 Session對象也能夠公開事件。這些事件能被global.asax文件或指定的文件中的事件處理程序處理。例如,當應用程序開始執行時,觸發 Application_Start事件;當應用程序結束時,觸發Application_End事件。Application的某些事件是每當頁面請求時觸發,而其他一些事件,例如Application_Error,則僅在特定情況下觸發。
示例18-2中的global.asax文件代碼說明了Application_Start 和Application_End事件。示例18-2中的Application_Start事件設置了兩個Application屬性:一個是名為 strConnectionString的字符串,一個是名為arBooks的字符串數組。事件處理程序方法調用一個名為WriteFile的輔助方法,它包含在global.asax文件中。該輔助方法將一個字符串寫入日志文件中。以下是示例18-2中的WriteFile方法代碼:
void WriteFile(string strText)
{
System.IO.StreamWriter writer =
new System.IO.StreamWriter(@"C:\test.txt",true);
string str;
str = DateTime.Now.ToString( ) + " " + strText;
writer.WriteLine(str);
writer.Close( );
}
WriteFile 是一個簡單的記錄日志的方法。該方法初始化一個基於文本文件的 StreamWriter對象,並對c:\test.txt進行硬編碼。它在文件中添加了一個時間戳,並寫入通過方法傳遞的字符串。 StreamWriter方法的布爾值參數為true,其表示如果文件已經存在,那么將文本行追加到文件中。如果文件不存在,則創建一個文件。
Application_End事件處理方法調用了另一個WriteFile方法,它添加了一個日志條目以記錄應用程序結束。
為了查看這兩個事件處理程序的結果,可對global.asax進行一些無意義的編輯,並保存文件。此時將強制結束應用程序。然后請求虛擬目錄中的任意URL地址。例如,使用上一章中的一個網頁——實際上無論哪一個——或者一個自己創建的網頁。示例18-3顯示了日志文件內容。
示例18-3:Test.txt摘錄
8/26/2006 5:46:23 PM Application Starting
8/26/2006 6:13:35 PM Application Ending
8/27/2006 10:17:39 PM Application Starting
8/27/2006 10:18:23 PM Application Ending
8/27/2006 10:18:36 PM Application Starting
如同Application對象的Start和End事件一樣,Session對象也擁有Session_ Start和Session_End事件。這將允許應用程序每次啟動和結束過程中為每個會話都運行代碼。
如示例18-4中高亮顯示的方法名所示,其包括了global.asax文件中所有可能的應用程序事件處理程序。在頁面請求被接受、處理和呈現過程中,可以容易地查看應用程序生命周期。
示例18-4:Global.asax事件說明
<%@ Application Language="C#" %>
以下是頁面請求觸發的所有事件,以觸發順序排序:
Application_BeginRequest
當ASP.NET開始處理每個請求時觸發。在這個事件處理中的代碼將在頁面或者服務處理請求之前執行。
Application_AuthenticateRequest
在驗證請求之前觸發。(正如第12章介紹的,驗證是確認用戶就是他所說的那個人的過程)在這個事件處理程序的代碼中允許實現自定義安全管道。
Application_AuthorizeRequest
在為請求授權之前觸發。(授權是確定是否請求用戶具有訪問資源的權限的過程,在
第12章已經介紹過)在這個事件處理程序的代碼中允許實現自定義安全管道。
Application_ResolveRequestCache
在ASP.NET確定是否應該生成新的輸出,或者由緩存填充前觸發。無論何種情況,都將執行該事件處理程序中的代碼。
Application_AcquireRequestState
在獲取會話狀態之前執行。
Application_PreRequestHandlerExecute
在將請求發送到服務於請求的處理程序對象之前觸發。當事件觸發后,頁面將由HTTP處理程序處理請求。
Application_PostRequestHandlerExecute
當HTTP處理程序與頁面請求一起完成時觸發。此時,Response對象將獲得由客戶端返回的數據。
Application_ReleaseRequestState
當釋放和更新試圖狀態時觸發。
Application_UpdateRequestCache
如果輸出被緩存,那么緩存更新時將觸發。
Application_EndRequest
當請求結束時執行。
Application_PreSendRequestHeaders
在向客戶端發送HTTP頭之前觸發。如果啟用響應緩存,這意味着直到所有數據都准備好(默認條件),都不會發送任何數據。該事件總是在Application_EndRequest事件之后。如果禁用響應緩存,那么無論何時將數據發送給客戶端,都將觸發該事件。響應控制由Page指令的一個屬性,或者Web服務的WebMethod屬性控制。
Application_PreSendRequestContent
向客戶端發送HTTP內容之前觸發。和Application_PreSendRequestHeaders事件一樣,Application_PreSendRequestContent事件能否被觸發取決於響應緩存是否可用。
以下列舉應用程序事件,它們在特定條件下觸發:
Application_Start
當應用程序啟動時觸發。當首次請求應用程序虛擬目錄中的任何頁面時,將啟動應用程序,同時如果應用程序已經運行,則不觸發該事件。
Application_End
應用程序結束時觸發。無論何時修改了配置文件(global.asax、global.asax.cs、
global.asax.vb或者web.config),或者服務器崩潰或者重啟,應用程序都將結束。通常在該事件處理程序中執行清除功能的代碼,例如關閉數據庫連接。
Session_Start
每個會話開始時觸發,這是放置具體會話代碼的地方。
Session_End
會話結束時觸發。它為保存存儲在會話中的任何數據提供了機會。
Application_Disposed
當CLR從內存中移除應用程序時觸發。
Application_Error
無論在應用程序中何時何處發生未處理的錯誤都將觸發。它提供了一個實現通用應用程序錯誤處理的好機會。
使用try...catch語句塊能夠在代碼中處理特定錯誤,也可以使用Page指令的ErrorPage屬性來捕獲頁面級錯誤。使用這些方式處理任何錯誤都不會觸發Application_Error事件。
為了測試新版的global.asax,在示例18-5中創建一個網頁。查看GlobalEvents站點。當該網頁運行時,將看到如圖18-4所示的頁面。
示例18-5:GlobalEvents網站的default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" %>
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
Global Events
Text="End Session"
OnClick="btnEndSession_Click" />
Text="Generate Error"
OnClick="btnError_Click" />
圖18-4:GlobalEvents
如圖18-4所示,可看到觸發了一系列應用程序事件。在這些事件執行的中途,呈現了.aspx頁面自身,接着是另一些應用程序事件。
警告:示例GlobalEvents必須在一個真實的IIS虛擬路徑下才能良好運行。
頁面第一次顯示時觸發Session_Start事件,而在隨后的顯示中則不再觸發該事件。 這是因為請求是相同的會話。單擊“End Session”按鈕,調用Session.Abandon方法,這將結束當前會話。下一次頁面被提交到服務器時,將再次觸發Session_Start 事件。
Post按鈕提供了一個簡單的再次提交頁面的方法。
示例18-4中大部分的應用程序事件處理程序都使用了Response.Write方法,以便顯示觸發的事件。然而,Application_Start和Application_End方法調用了WriteFile方法。如果在這些事件處理程序中試圖使用Response.Write方法,那么在頁面中將不會
顯示。因為那時用於呈現的頁面會話還沒有運行。但是,當檢查日志文件c:\test.txt時,將看到應用程序啟動和結束所顯示的條目。
示例18-4所示的global.asax文件說明了一種使用Application_Error事件的方法。以下列舉了這些代碼:
protected void Application_Error(Object sender, EventArgs e)
{
string strError;
strError = Server.GetLastError( ).ToString( );
if (Context!= null)
Context.ClearError( );
Response.Write("Application_Error" + "
");
Response.Write("Error Msg: " + strError + "
" +
"End Error Msg
");
}
該事件處理程序使用HttpServerUtility對象的GetLastError方法,以報告最后出現的錯誤。這個錯誤被轉換為一個字符串,並被指定給一個字符串變量:
strError = Server.GetLastError( ).ToString( )
接下來調用HttpContext對象的ClearError方法來清除目前HTTP請求中的所有錯誤:
Context.ClearError( )
如果沒有將錯誤清除,那么錯誤將顯示在客戶端瀏覽器,並且還是無法看見Respons- e.Write方法的顯示結果。
最后,Response.Write方法顯示一個信息,當前的錯誤將顯示在客戶端。
另一種向用戶報告錯誤的方式是顯示自定義錯誤處理頁面。為此,需要使用以下代碼行替代Application_Error事件處理程序中的Response.Write方法:
Response.Redirect("CustomErrorPage.aspx?Msg=" +
Server.UrlEncode(strError));
以上代碼行調用HttpServerUtility對象的UrlEncode方法,其將錯誤信息作為一個QueryString參數傳遞給CustomErrorPage.aspx頁面中的自定義錯誤處理代碼。 CustomErrorPage.aspx頁面有一個名為lblMessage的Label控件。以下是頁面中的Page_Load方法代碼:
void Page_Load(Object Source, EventArgs E)
{
lblMessage.Text = Request.QueryString["Msg"];
}
Default.aspx中的Generate Error按鈕故意觸發一個錯誤,以便查看錯誤處理。該按鈕的單擊事件處理程序的代碼如下所示,它將除零異常:
protected void btnError_Click(object sender, EventArgs e)
{
int a = 5;
int b = 0;
int c;
c = a / b;
}
服務器端包括
使用服務器端包括能夠實現在應用程序中包含外部源代碼文件。在編譯之前,包括文件中的代碼將被添加到global.asax文件中。盡管應用程序的語言可能與包括文件的語言不同,但是用於包括文件的語言必須與global.asax文件所使用的語言匹配。
下面是用於服務器端的語法:
在這個句法中,PathType類型可以是表18-1所示之一。
表18-1 PathType屬性
| 路徑類型 | 說 明 |
| File | 文件名是包含global.asax文件的目錄的相對路徑 |
| Virtual | 文件名是包含網站虛擬目錄的虛擬路徑 |
查看示例18-4所示的global.asax文件,將下面的代碼添加到第二行中:
創建一個新的名為IncludeFile.cs的文本文件,將該文件和global.asax存儲在同一目錄下。這個文件需要與global.asax文件一樣的一對腳本標簽。
將global.asax頁面中的WriteFile方法復制到包括文件中,然后注釋(或者刪除)global.asax頁面中的WriteFile方法。這樣包括文件應類似於示例18-6。
示例18-6:具有包括文件的global.asax
如果運行任意一個網頁,那么將不會與先前有什么區別,因為您所做的只是把一個文件中的代碼轉移到另外一個文件中。
如果CLR監視global.asax文件的變化,並和重新啟動應用程序一樣,CLR也監視包括文件的變化。如果包括文件發生變化,那么應用程序也會重新啟動。
對於在多個應用程序中所包括的相同標准代碼而言,包括文件非常有用。這些通用代碼可能包括數據庫訪問方法、寫入日志記錄、錯誤處理管道、登錄或者每個應用程序的基礎類型代碼片段。
對象聲明
在global.asax文件中包括代碼的另一個方法是是聲明object標簽。這些聲明的靜態對象要么是Application,或者是Session對象。這樣就可以在應用程序或者每個會話過程中使用。
評論這張
轉發至微博
轉發至微博
