Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 597|回复: 0

MVC扩展Filter,通过继承HandleErrorAttribute,使用log4net或ELMAH组件记录服务端500错误、HttpException、Ajax异常等

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-8-27 09:41:59 | 显示全部楼层 |阅读模式

    □ 接口

    public interface IExceptionFilter
    {
        void OnException(ExceptionContext filterContext);
    }

    ExceptionContext继承于ControllerContext,从中可以获得路由数据route data、HttpContext。

     

    □ 的HandleErrorAttribute是对IExceptionFilter的实现,默认是启用的

    public static void RegisterGlobalFilters(GlobalFiltersCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }

     

      使用默认的HandleErrorAttribute

    □ 让Shared/Error.cshtml的出错页报错

    前提是,在Web.config中配置:

    <customErrors mode="On"></customErrors>

     

    □ 根据不同错误类型显示不同的错误页

            [HandleError(ExceptionType = typeof(DbException),View = "")]
            [HandleError(ExceptionType = typeof(ApplicationException), View = "")]
            public ActionResult SomeAction()

     

    □ HandleErrorAttribute的不足之处

    1、只是显示错误页,无法记录错误日志
    2、只能捕获500错误
    3、不能捕获Controller以外的错误

     

      继承HandleErrorAttribute自定义异常处理

    使用log4net记录错误日志,并能记录AJAX错误,返回状态码为500的服务端错误。

     

    需要一个显示错误信息的类:

    namespace MvcApplication1.Models
    {
        public class HandleErrorInfo
        {
            public HandleErrorInfo(Exception exception, string actionName, string controllerName)
            {
                this.Exception = exception;
                this.ControllerName = controllerName;
                this.ActionName = actionName;
            }
            public string ActionName { get; set; }
            public string ControllerName { get; set; }
            public Exception Exception { get; set; }
        }
    }

     

    引用log4net组件,继承HandleErrorAttribute自定义异常,使之能记录状态码为500的服务端错误,并能以json形式返回ajax相关异常。

    using System.Web;
    using System.Web.Mvc;
    using log4net;
     
    namespace MvcApplication1.Extension
    {
        public class PowerfulHandleErrorAttribute : HandleErrorAttribute
        {
            private readonly ILog _logger;
     
            public PowerfulHandleErrorAttribute()
            {
                _logger = LogManager.GetLogger("MyLogger");
            }
     
            public override void OnException(ExceptionContext filterContext)
            {
                if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
                {
                    return;
                }
     
                if (new HttpException(null, filterContext.Exception).GetHttpCode() != 500)
                {
                    return;
                }
     
                if (!ExceptionType.IsInstanceOfType(filterContext.Exception))
                {
                    return;
                }
     
                //如果是AJAX请求返回json
                if (filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
                {
                    filterContext.Result = new JsonResult()
                    {
                        JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                        Data = new
                        {
                            error = true,
                            message = filterContext.Exception.Message
                        }
                    };
                }
                else
                {
                    var controllerName = (string)filterContext.RouteData.Values["controller"];
                    var actionName = (string)filterContext.RouteData.Values["action"];
                    var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
     
                    filterContext.Result = new ViewResult()
                    {
                        ViewName = View,
                        MasterName = Master,
                        ViewData = new ViewDataDictionary(model),
                        TempData = filterContext.Controller.TempData
                    };
                }
     
                _logger.Error(filterContext.Exception.Message, filterContext.Exception);
                filterContext.ExceptionHandled = true;
                filterContext.HttpContext.Response.Clear();
                filterContext.HttpContext.Response.StatusCode = 500;
     
                filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
            }
        }
    }
     

     

    以上PowerfulHandleErrorAttribute错误,只能处理服务端状态码500错误。还可以在全局中设置:当出现HttpException异常的时候,返回对应的错误提醒视图。

           //处理filter遗漏的错误
            protected void Application_Error(object sender, EventArgs e)
            {
                var httpContext = ((MvcApplication) sender).Context;
     
                var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
                var currentController = "";
                var currentAction = "";
                if (currentRouteData != null)
                {
                    if (currentRouteData.Values["controller"] != null &&
                        !string.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
                    {
                        currentController = currentRouteData.Values["controller"].ToString();
                    }
     
                    if (currentRouteData.Values["action"] != null &&
                        !string.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
                    {
                        currentAction = currentRouteData.Values["action"].ToString();
                    }
                }
     
                var ex = Server.GetLastError();
                var controller = new ErrorController();
                var routeData = new RouteData();
                var action = "Index";
                if (ex is HttpException)
                {
                    var httpEx = ex as HttpException;
                    switch (httpEx.GetHttpCode())
                    {
                        case 404:
                            action = "NotFound";
                            break;
                        default:
                            action = "Index";
                            break;
                    }
                }
     
                httpContext.ClearError();
                httpContext.Response.Clear();
                httpContext.Response.StatusCode = ex is HttpException ? ((HttpException) ex).GetHttpCode() : 500;
                httpContext.Response.TrySkipIisCustomErrors = true;
                routeData.Values["controller"] = "Error";
                routeData.Values["action"] = action;
     
                controller.ViewData.Model = new HandleErrorInfo(ex, currentController, currentAction);
                ((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
            }
     

     

    为此,还需要定义一个ErrorController,当然还有与之对应的错误提示视图:

    using System.Web.Mvc;
     
    namespace MvcApplication1.Controllers
    {
        public class ErrorController : Controller
        {
            public ActionResult Index()
            {
                return View();
            }
     
            public ActionResult NotFound()
            {
                return View();
            }
     
        }
    }
     

     

      使用ELMAH记录全局异常

    using System.Web.Mvc;
    using Elmah;
     
    namespace MvcApplication1.Extension
    {
        public class ElmahHandleErrorAttribute : HandleErrorAttribute
        {
            public override void OnException(ExceptionContext filterContext)
            {
                base.OnException(filterContext);
     
                if (filterContext.ExceptionHandled)
                {
                    ErrorSignal.FromCurrentContext().Raise(filterContext.Exception);
                }
            }
        }
    }
     

     

    参考资料:
    Exception Handling in ASP.NET MVC

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-22 11:55 , Processed in 0.063854 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表