文章出處

要在ASP.NET中處理好自定義錯誤(Custom Errors)首先要拋棄使用web.config\customErrors。

<customErrors mode="RemoteOnly" defaultRedirect="/error/error.htm">
    <error statusCode="404" redirect="/error/404.htm" />
</customErrors>

使用web.config\customErrors最大的一個缺點是在顯示自定義錯誤頁面時會重定向:

http://www.cnblogs.com/error/error.htm?aspxerrorpath=/cmt/p/3789549.html

這會帶來2個麻煩:

1. 會造成用戶反饋問題時提供的是重定向后的URL。

2. 會造成用戶無法通過刷新瀏覽器進行重試,或者問題解決后通過刷新瀏覽器恢復正常。

我們目前想到的最佳處理方式是在Global.asax.cs的Application_Error中進行處理。

代碼如下:

protected void Application_Error(Object sender, EventArgs e)
{
    Exception lastError = Server.GetLastError();

    if (lastError != null)
    {
        if (lastError is HttpException)
        {
            if (((HttpException)lastError).ErrorCode == 404)
            {
                Response.StatusCode = 404;
                Server.ClearError();
                return;
            }
        }
        CNBlogs.Infrastructure.Logging.Logger.Default.Error("Application_Error", lastError);
        Response.StatusCode = 500;
        Server.ClearError();
    }
}

由于我們在IIS中指定了404/500錯誤的自定義錯誤頁面,所以這里只需要返回狀態碼(需要IIS 7.0以上)。

IIS Error Pages

這樣處理后,還可以方便地在顯示自定義錯誤之前記錄到log4net日志。

另外需要注意的是一定要Server.ClearError(),不然ASP.NET會根據web.config\customErrors進行繼續處理(代碼中的自定義錯誤處理就會失效),錯誤信息也會被記錄到Windows日志(既然我們已經記錄到了log4net日志,就沒必要再記錄到Windows日志)。

你也許會問,幾行代碼就能解決的如此簡單的問題,值得興師動眾寫篇博客還要發在首頁?

值!因為之前我們沒有認真對待這個地方的問題,多次為此付出了代價。也許園子里還有人沒有注意這個地方的問題。

踩自己的坑,寫自己的博客,然后讓別人無坑可踩,我想這也是寫博客的一個價值體現吧。

【更新】

根據@NatureSexy的建議,改進了代碼:

protected void Application_Error(Object sender, EventArgs e)
{
    var lastError = Server.GetLastError();

    if (lastError != null)
    {
        var httpError = lastError as HttpException;
        if (httpError != null && httpError.ErrorCode == 404)
        {
                Response.StatusCode = 404;
                Server.ClearError();
                return;
        }

        CNBlogs.Infrastructure.Logging.Logger.Default.Error("Application_Error", lastError);
        Response.StatusCode = 500;
        Server.ClearError();
    }
}

【2014年12月27日更新】

Application_Error代碼更新,之前的代碼中沒有處理ASP.NET的400錯誤情況。

protected void Application_Error(Object sender, EventArgs e)
{
    var lastError = Server.GetLastError();
    if (lastError != null)
    {
        var httpError = lastError as HttpException;
        if (httpError != null)
        {
            //ASP.NET的400與404錯誤不記錄日志,并都以自定義404頁面響應
            var httpCode = httpError.GetHttpCode();
            if (httpCode == 400 || httpCode == 404)
            {
                Response.StatusCode = 404;//在IIS中配置自定義404頁面
                Server.ClearError();
                return;
            }
            Logger.Default.Error("Application_Error_" + httpCode, httpError);
        }

        //對于路徑錯誤不記錄日志,并都以自定義404頁面響應
        if (lastError.TargetSite.ReflectedType == typeof(System.IO.Path))
        {
            Response.StatusCode = 404;
            Server.ClearError();
            return;
        }

        Logger.Default.Error("Application_Error", lastError);
        Response.StatusCode = 500;
        Server.ClearError();
    }
}

注:如果用的是MVC,需要注釋下面的代碼:

//filters.Add(new HandleErrorAttribute());

文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜

    大師兄 發表在 痞客邦 留言(0) 人氣()