圖7-17 Custom Errors選項卡 現在Chapter07子目錄中的頁面出現一個ASP錯誤時,就會打開定制的錯誤頁面。 2. 使用定制的錯誤頁面 在瀏覽器中打開Chapter07目錄并選擇到“Using a Custom Error Page”的鏈接,這個頁面顯示了一系列用于產生各種類型的錯誤的按鈕,點擊標有“Load a Page with a Syntax error”的按鈕,如圖7-18所示:
圖7-21 cause_error.asp頁面的選擇框 在本章下面部分,將再討論這一問題,同時也可以了解“Cause An Error”頁面上的其他按鈕所提供的其他種類的錯誤信息。注意有一些按鈕能夠比其他的按鈕能夠提供更多信息。特別是只有最后一個按鈕給出ASP錯誤代碼的值(這里是ASP 0177)。 (1) “Cause An Error”頁面的功能 與先前討論的示例頁面一樣,引起錯誤的頁面使用同樣的技術,用<Form>把值提交給同一個頁面。然后ASP程序查看窗口上點擊的是那個SUBMIT按鈕,然后運行代碼的相應部分。同時查看是否頁面上兩個復選框是否選中,如果是這樣,程序首先設置一個或兩個會話級的變量以指明這一點。 <% 'see if we are displaying error and debug information 'set session variables to retrieve in the custom error page If Len(Request.Form("chkShowError")) Then Session("ShowError") = "Yes" Else Session("ShowError") = "" End If If Len(Request.Form("chkShowDebug")) Then Session("ShowDebug") = "Yes" Else Session("ShowDebug") = "" End If ... %> 由于使用了Server.Transfer,當錯誤發生時,正在運行的網頁的整個ASP環境由IIS傳給定制錯誤頁面。然而,腳本變量的值并沒有傳給定制錯誤頁面,所以必須使用Session變量,或者把值添加到Request.Form或Request.QueryString集合以便把值傳送給定制錯誤頁面。 設置了Session變量之后,程序繼續查看點擊了哪個按鈕。每個類型的錯誤(除了第一類型外),都是由運行相應的ASP代碼產生的,第一類型的錯誤需要調用另一個頁面。 ... 'look for a command sent from the FORM section buttons If Len(Request.Form("cmdSyntax")) Then Response.Clear Response.Redirect "syntax_error.asp" End If If Len(Request.Form("cmdParamType")) Then intDate = "error" intDay = Day(intDate) End If If Len(Request.Form("cmdArray")) Then Dim arrThis(3) arrThis(4) = "Causes an error" End If If Len(Request.Form("cmdFile")) Then Set objfso = Server.CreateObject("Scripting.FileSystemObject") Set objTStream = objFSO.OpenTextFile("does_not_exist.txt") End If If Len(Request.Form("cmdPageCount")) Then Set objPageCount = Server.CreateObject("MSWC.PageCounter") objPageCount.WrongProperty = 10 End If If Len(Request.Form("cmdObject")) Then Set objThis = Server.CreateObject("Doesnot.Exist") End If %> (2) 定制錯誤頁面的工作 知道了如何創建錯誤后,讓我們來看看定制的錯誤頁面。在前面的章節里已經知道了構建網頁需要的理論,這里再概要地描述一下其工作過程。第一步是關閉缺省的錯誤處理器以便頁面程序不被另一個錯誤中斷。第二步通過創建一個新的ASPError對象收集原始錯誤信息。進行這個工作時要格式化一些值,并把它們轉換成合適的數據類型。 <% 'prevent any other errors from stopping execution On Error Resume Next
'get a reference to the ASPError object Set objASPError = Server.GetLastError()
'get the property values strErrNumber = CStr(objASPError.Number) 'normal error code strASPCode = objASPError.ASPCode 'ASP error code (if available) If Len(strASPCode) Then strASPCode = "'" & strASPCode & "' " Else strASPCode = "" End If strErrDescription = objASPError.Description strASPDescription = objASPError.ASPDescription strCategory = objASPError.Category 'type or source of error strFileName = objASPError.File 'file path and name strLineNum = objASPError.Line 'line number in file strColNum = objASPError.Column 'column number in line If IsNumeric(strColNum) Then 'if available convert to integer lngColNum = CLng(strColNum) Else lngColNum = 0 End If strSourceCode = objASPError.Source 'source code of line ... 現在構建一個錯誤報告字符串,這段程序看起來復雜,但實際上僅是一系列If ...Then語句的嵌套,用以產生良好的報告格式,沒有任何空的段落。如果錯誤是語法錯誤,來自ASPError對象的Source屬性的源代碼可在strSourceCode變量中得到,可以使用這個變量及lngColNum的值(從ASPError對象的Column屬性中得到)增加一個標記用來指明在源程序中的什么地方發現了錯誤。 ... 'create the error message string strDetail = "ASP Error " & strASPCode & "occurred " & Now If Len(strCategory) Then strDetail = strDetail & " in " & strCategory End If strDetail = strDetail & vbCrlf & "Error number: " & strErrNumber _ & " (0x" & Hex(strErrNumber) & ")" & vbCrlf If Len(strFileName) Then strDetail = strDetail & "File: " & strFileName If strLineNum > "0" Then strDetail = strDetail & ", line " & strLineNum If lngColNum > 0 Then strDetail = strDetail & ", column " & lngColNum If Len(strSourceCode) Then 'get the source line so put a ^ marker in the string strDetail = strDetail & vbCrlf & strSourceCode & vbCrlf _ & String(lngColNum - 1, "-") & "^" End If End If End If strDetail = strDetail & vbCrlf End If strDetail = strDetail & strErrDescription & vbCrlf If Len(strASPDescription) Then strDetail = strDetail & "ASP reports: " & strASPDescription & vbCrlf End If ... (3) 記錄錯誤 用名為strDetail的字符串變量創建了錯誤報告后,可以像在第5章中做的那樣,采用FileSystemObject對象把它追加到日志文件中。如果成功,布爾型“failed flag”變量將被設置成False。 ... 'now log error to a file. Edit the path to suit your machine. 'you need to give the IUSR_machinename permission to write and modify 'the file or directory used for the log file: strErrorLog = "c:/temp/custom_error.log" Set objFSO = Server.CreateObject("Scripting.FileSystemObject") Set objTStream = objFSO.OpenTextFile(strErrorLog, 8, True) '8 = ForAppending If Err.Number = 0 Then objTStream.WriteLine strDetail & vbCrlf If Err.Number = 0 Then objTStream.Close blnFailedToLog = False Else blnFailedToLog = True End If %> (4) 跳轉到另一個頁面 現在準備在網頁中創建一些輸出。在此之前,需要檢查錯誤細節以確定下一步要做什么。例如,可用ASPError對象的Number或其他屬性檢查錯誤類型。在這里,可認為“Type Mismatch”錯誤不是代碼中有錯誤,可能是由于用戶在文本框中輸入錯誤數據產生的。所以不顯示這個網頁的剩余部分,而是跳轉到另一個網頁 If objASPError.Number = -2146828275 Then ' 0x800A000D - type mismatch Response.Clear Response.Redirect "/" ' go to the Home page End If 是否決定這樣做依賴于你自己的情況以及你打算發現、記錄或顯示的錯誤類型。需要注意的是,因為我們不想把目前的網頁環境傳送到新的網頁上,所以選擇使用Reponse.Redirect語句而不是用Server.Transfer語句。 (5) 顯示錯誤信息 最后,顯示錯誤報告和其他信息以及返回到上一個網頁或主頁的按鈕。 <% 'see if the logging to file failed 'if so, display message If blnFailedToLog Then Response.Write "<B>WARNING: Cannot log error to file '" & strErrorLog & "'</B>.<P>" End If
'see if we are displaying the error information If Session("ShowError") = "Yes" Then %> <PRE><% = Server.HTMLEncode(strDetail) %></PRE> <% End If
'see if we are displaying the debug information If Session("ShowDebug") = "Yes" Then Server.Transfer "debug_request.asp"
'create the buttons to return to the previous or Home page strReferrer = Request.ServerVariables("HTTP_REFERER") If Len(strReferrer) Then %> <FORM ACTION="<% = strReferrer %>"> <INPUT TYPE="SUBMIT" NAME="cmdOK" VALUE=" "> Return to the previous page<P> </FORM> <% End If %> <FORM ACTION="/"> <INPUT TYPE="SUBMIT" NAME="cmdOK" VALUE=" "> Go to our Home page<P> </FORM> 對上面這段程序需要注意的是:在定制錯誤頁面里,不能使用Server.Execute方法。如果我們這樣做的話,至少程序不能正常工作。當程序把執行轉到特定的網頁時,程序不會再返回到當前網頁,這就是我們使用Server.Transfer方法載入顯示調試信息的網頁的原因。這是下一部分要討論的問題。