zoukankan      html  css  js  c++  java
  • ASP.NET中处理自定义错误的最佳方式

    要在ASP.NET中处理好自定义错误(Custom Errors)首先要抛弃使用web.configcustomErrors。

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

    使用web.configcustomErrors最大的一个缺点是在显示自定义错误页面时会重定向:

    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.configcustomErrors进行继续处理(代码中的自定义错误处理就会失效),错误信息也会被记录到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());
  • 相关阅读:
    ASP.NET Web应用程序与ASP.NET Web服务应用程序的区别
    【你必须知道的.NET】:【大话String】
    获取SQLServer数据库中所有表
    Window_Open详解收藏
    关于数据实现批量删除
    asp.net mvc 图形解析说明原理
    【转载】:C#语言
    泛型参数的约束
    SQL 常用函数小结
    [转载]:C#两种不同的存储过程调用方法
  • 原文地址:https://www.cnblogs.com/dudu/p/aspnet_custom_error.html
Copyright © 2011-2022 走看看