ASP.NET網站中設定404自訂錯誤頁面

來源:互聯網
上載者:User

標籤:完全   perror   com   server   run   選擇   href   解決方案   應用程式   

在用ASP.NET WebForm開發一個網站時,需要自訂404錯誤頁面. 做法是這樣的

在網站根目錄下建立了一個404.html的錯誤頁面,然後在Global.asax檔案中,加入如下代碼:

<%@ Application Language="C#" %><script runat="server">    void Application_Error(object sender, EventArgs e)    {        Response.StatusCode = 404;        Server.Transfer("/404.html");        Server.ClearError();    }</script>

然後運行網站,比如隨便輸入一個111.aspx時,發現在chrome上會自動redirect到這個404.html, 但是在IE上時,卻不會。

在網上尋找原因,找到如下答案:

 果然,在這個頁面中加入一些內容後,這個問題就解決了

 

另外,這種設定404錯誤頁面,還有一個問題就是,當你在網址中輸入不存在的比如111.aspx時,它會自動轉入自訂的404.html

但是當你在網址中輸入不存在的111, 沒有尾碼名aspx時,它就不會顯示自訂的404.html了

為什麼會出現這種情況呢 ? 應該怎麼解決呢 ?

 

解決方案:  你需要在web.config中進行配置,在 <system.webServer>配置節點中加入如下語句

 <httpErrors errorMode="Custom" existingResponse="Replace">   <clear />   <error statusCode="404" path="404.html" />   </httpErrors>

 

詳細的處理ASP.NET網站自訂錯誤頁面方法,可以參考如下這篇文章,寫的很好

轉載自 http://edi.wang/post/2014/1/11/iis7-aspnet-custom-error-best-practice

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------針對IIS7以上的ASP.NET網站自訂錯誤頁面與異常日誌總結

自訂錯誤頁面和異常記錄是個很古老的話題了,但依舊可以讓人爆到現在。在我做了無數次實驗並總結經驗和原則後,寫下本文,已警後人。

本文的範圍和限制

  1. 本文僅僅適用於部署在IIS7或以上版本中的ASP.NET 4.0整合模式應用程式。IIS7以上的意思是Windows Server 2008以上伺服器適用。我已在WS2012R2,IIS8上測過。
  2. 本文的方法均適用於ASP.NET WebForm和MVC應用程式。

本文針對的問題

  1. 靜態錯誤頁面好還是動態錯誤頁面好?我該如何設計ASP.NET網站錯誤處理?
  2. 我不希望錯誤頁面後面跟上aspxerrorpath=…這個小尾巴。
  3. 我的自訂錯誤頁面在VS裡調試是好的,為什麼部署到伺服器上就出不來了?
  4. 我的自訂錯誤頁面可以正常顯示,但為什麼返回的Http狀態代碼不正確?
  5. 異常日誌該怎樣記錄,有沒有比較好的實踐?

一、錯誤頁面的選擇

選擇靜態html頁面作為錯誤頁,還是使用.aspx或是MVC View來顯示錯誤頁面好?這個問題許多人的偏好都不一樣。我強烈建議大家用html靜態頁面作為錯誤頁。請看分析:

首先,用動態網頁面的人,無非是為瞭解決三個問題:顯示錯誤摘要、記錄日誌、返回正確的狀態代碼。但是,動態網頁面最大的問題在於,它們本身是要經過ASP.NET和後台代碼處理的,萬一你的後台代碼是爆的,或者ASP.NET自己爆了,那你的錯誤頁面一旦被請求,本身就會引發另一個錯誤。而靜態html是不會有這個問題的。至於在MVC裡專門建一個ErrorController的做法就更不可取了。MVC是基於ASP.NET之上的,MVC的Controller只能抓MVC自己的錯誤,抓不到ASP.NET的錯誤,意思就是說,當你的錯誤並不在MVC層面上的時候,ErrorController沒有任何用武之地。例如,當你部署的MVC應用程式缺少MVC的dll時候,MVC架構本身都跑不起來,這個錯誤如何去抓?

另外,我認為在一個Internet網站上,絕不應該向訪客顯示任何的錯誤摘要。這是非常不安全的。所以完全沒有必要用動態網頁面。

至於返回正確狀態代碼的問題是這樣的:不少小夥伴發現自己的錯誤頁面能夠顯示,但返回的狀態代碼是200OK,所以無奈之下用動態網頁面,寫上Response.StatusCode = 500這樣的代碼來強擼。這個在稍後的文章裡有解決方案,所以不要為了狀態代碼而冒險用動態網頁面。有的小夥伴會問,我唯寫一筆Response.StatusCode=500能有什麼風險?呵呵,想想這種情況:404.cshtml,razor引擎的dll不見了……

另外,一個原則是:錯誤頁面應當是獨立的。如果你的靜態頁面要用到圖片和CSS等外部資源,建議嵌入在頁面裡邊,做成單檔案的,以免顯示錯誤頁面時請求相關資源再次引發異常。小夥伴又要問了,請求個CSS和圖片什麼的,腫麼會引發異常呢?那你看看這個:resources.axd?image=…,呵呵。

那麼用了靜態頁面以後,記錄日誌怎麼辦呢?正確的方法應該是交給Global.asax中的“Application_Error”事件處理。稍後會有翔解。

二、配置錯誤頁面:customErrors VS httpErrors

首先,錯誤頁面的顯示方式有兩種。如果你開啟IIS,會看到兩個配錯誤頁的地方:.NET Error Pages和Error Pages。

 

站在開發人員的角度來說,ASP.NET Section下的“.NET Error Pages”就是web.confg/system.web/customErrors節點。而IIS Section下的”Error Pages”是web.config/system.webServer/httpErrors節點,這個是IIS7以上特有的。

任何在IIS上對這兩處的更改其實都是在修改web.config檔案。

那麼我們該用哪一個來配置自訂錯誤頁呢?我的一個原則是:讓IIS向使用者展示錯誤頁面,而不要依賴於ASP.NET。 猿因如下:

CustomError的問題:

a)  在預設情況下,CustomError會採用302重新導向的方式來展示錯誤頁面,如果用戶端請求了一個404的頁面,那它得到的將會是一個302緊接著一個200OK,對於人類來說這是OK的,畢竟使用者看到了友好的錯誤頁面,但搜尋引擎會認為這個不存在的地址是正常的頁面,並把你的404頁面收入搜尋結果。並且每次引發錯誤,URL後邊都會跟上aspxerrorpath這個小尾巴,比如:

http://yoursite.com/404.html?aspxerrorpath=/somethingnotexsit

b) 在配置了redirectMode=“ResponseRewrite”後,會引發一個問題,09年就有人當bug提交到MS Connect上了,但目前微軟不打算fix這個bug。即該模式在VS內建的ASP.NET Development Server上是有效,瀏覽器顯示的是解析後的HTML頁面,而部署到IIS上之後,瀏覽器顯示是raw html,即你的錯誤頁面的HTML代碼。並且該行為不具有確定性,天曉得你的網站換個環境部署又會爆成什麼樣。

c)  IIS7以上版本的特殊性:在整合模式下,IIS的錯誤頁面會優先於ASP.NET錯誤頁面,即IIS的預設錯誤頁會覆蓋你配置的CustomErrors頁面,這就是為什麼你在VS下調試是好的,部署到伺服器上就爆了。

在IIS7之後,取決於你的配置,使用者的請求並不都一定在ASP.NET管線上處理。如果引發異常的地方不在ASP.NET,那就不會顯示CustomErrors的錯誤頁面。

所以,我強烈建議大家用httpErrors節點替代CustomErrors來配置錯誤頁面。

三、File還是ExecuteURL:httpErrors的正確配法

先貼一個正確的配置範例:是用File配的。

注意兩處地方:

  1. 斜杠是Windows檔案路徑的反斜線“\”而不是網址URL的斜杠“/”
  2. Path不要以“~”或“\”開頭

不要問我為什麼,我也不知道,反正這麼弄就是好的。

如果你不幸用了ExecuteURL,你會發現URL路徑只能以“/”開頭:

並且你的錯誤頁會返回200OK而不是正確的404、500等錯誤碼。這在我以前的文章裡寫過:

http://diaosbook.com/Post/2012/6/24/correct-way-to-implement-custom-error-page-return-statecode-instead-of-http-200

而用File的意思是,當錯誤被爆出來之後,IIS會把目標File,比如404.html的內容,塞到當前的Response流裡面,保持Http狀態代碼依舊是404。這就是我們想要的。

四、異常日誌記錄

文章在一開始就提了個問題,木有了動態網頁面,怎麼記錄錯誤記錄檔?我的做法是在Global.asax裡處理。

Application_Error事件範例代碼如下:

var exception = HttpContext.Current.Server.GetLastError();if (null != exception){    // by default 500    var statusCode = (int)HttpStatusCode.InternalServerError;    if (exception is HttpException)    {        statusCode = new HttpException(null, exception).GetHttpCode();    }    else if (exception is UnauthorizedAccessException)    {        // to prevent login prompt in IIS        // which will appear when returning 401.        statusCode = (int)HttpStatusCode.Forbidden;    }    if ((LogHttpNotFound && statusCode == 404) || statusCode != 404)    {        if (null != _loggerFunc)        {            LoggerFunc(string.Format("ASP.NET Error Captured, Request URL: {0}, Exception:",                HttpContext.Current.Request.Url), exception);        }    }    ExceptionInfo = exception.Message;    _statusCode = statusCode;}

一個小小的建議是不要記錄404錯誤,因為你的網站在Internet上會被各種搜尋引擎、掃描工具和駭客菊爆,有一種攻擊手段是通過字典猜解目錄,返回404就是不存在,返回403就是存在。所以,當你碰到這種無聊駭客的時候,如果記錄了404請求,那你的日誌會非常的大……

我記日誌用的組件是NLog,配置簡單,使用容易。Log4net這貨已經好久沒更新了。

如果你決定自己設計日誌模組,那要記住兩個原則:

日誌模組本身並不能因為自己爆掉而影響整個系統運行,即任何在日誌模組裡的異常不應該向外冒泡。

考慮並發寫日誌的情況,日誌操作應該是Fire and Forget的,不能讓應用程式等待日誌寫入。

五、總結

  1. 採用靜態html頁面作為錯誤頁。
  2. 採用httpErrors配置錯誤頁面,目的是相容IIS7以上環境、返回正確錯誤碼、去掉aspxerrorpath小尾巴。
  3. 日誌記錄寫在Global.asax裡,在Application_Error事件中記錄

ASP.NET網站中設定404自訂錯誤頁面

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.