本文实现对MVC异常处理功能,借此来讨论ASP.NET MVC中拦截器的使用方法。

第一步:写一个自己的异常过滤器,让它继承HandleErrorAttribute类 然后重写OnException()这个方法  (注:HandleErrorAttribute 类已经继承了FilterAttribute, IExceptionFilter这两个接口,并实现了它们,所以这我们只要继承HandleErrorAttribute就可以了)

[csharp] view plaincopy

  1. using System;  

  2. using System.Collections.Generic;  

  3. using System.Linq;  

  4. using System.Web;  

  5. using System.Web.Mvc;  

  6.   

  7. namespace Itcast.CMS.WebApp.Controllers.Filters  

  8. {  

  9.     public class MyExceptionFilterAttribute : HandleErrorAttribute  

  10.     {  

  11.   

  12.         Itcast.CMS.Common.LogHelper log = new Common.LogHelper();//创建一个log4net日记对象  

  13.         public override void OnException(ExceptionContext filterContext)  

  14.         {  

  15.               

  16.             //获取或设置一个值,该值指示是否已处理异常。如果已处理异常,则为 true;否则为 false。  

  17.             if (filterContext.ExceptionHandled==true)  

  18.             {  

  19.                 HttpException httpException = filterContext.Exception as HttpException;  

  20.                 //为什么要特别强调500 因为MVC处理HttpException的时候,如果为500 则会自动  

  21.                 //将其ExceptionHandled设置为true,那么我们就无法捕获异常  

  22.                 if (httpException.GetHttpCode() == 500)  

  23.                 {  

  24.                     return;  

  25.                 }                  

  26.             }  

  27.             //创建一个HttpException对象,使用filterContext.Exception来对它初始化(其实就是将filterContext.Exception转换成HttpException类型)  

  28.             HttpException httpExce = new HttpException(null, filterContext.Exception);  

  29.             //HttpException httpExce = filterContext.Exception as HttpException;  

  30.               

  31.             if (httpExce != null)  

  32.             {  

  33.                 if (httpExce.GetHttpCode() == 404)  

  34.                 {  

  35.                     HttpContext.Current.Response.Redirect("/Error/NotFound");//跳转到404错误页面  

  36.                 }  

  37.                 else if (httpExce.GetHttpCode() == 500)  

  38.                 {  

  39.                     //也可以这样写  

  40.                     filterContext.HttpContext.Response.Redirect("/Error/ServerError");//跳转到500服务器错误页面  

  41.                 }  

  42.             }  

  43.              

  44.             //调用log4net来记录日记  

  45.             log.Error("错误:" + filterContext.Exception.Message, filterContext.Exception);  

  46.   

  47.             filterContext.ExceptionHandled = true;    //将异常设置为已处理       

  48.               

  49.         }  

  50.   

  51.     }  

  52. }  

第二步:将自己刚刚写的过异常滤器注册到MVC的全局过滤器中去。只要到App_Start这个文件夹下的FilterConfig.cs文件中注册一下就可以,

将默认的 filters.Add(new HandleErrorAttribute()); 这段代码 替换为filters.Add(new MyExceptionFilterAttribute()); 具体代码如下

[csharp] view plaincopy

  1. using Itcast.CMS.WebApp.Controllers.Filters;  

  2. using System.Web;  

  3. using System.Web.Mvc;  

  4.   

  5. namespace Itcast.CMS.WebApp  

  6. {  

  7.     public class FilterConfig  

  8.     {  

  9.         public static void RegisterGlobalFilters(GlobalFilterCollection filters)  

  10.         {  

  11.             filters.Add(new MyExceptionFilterAttribute());  

  12.         }  

  13.     }  

  14. }  

 做好以上两步,当MVC中有异常的时候,就会自动跳转到自己的过滤器中进行处理了。(注:不需要在类,或者方法前面加[MyExceptionController])只要做好前面两步就可以了


其实有的时候报404错误,也就是在路由阶段就没有通过,也就是没有到达控制器,所以无法进入到我们的过滤器。(去网上查了一下,都说404不是属 于一个异常,仅仅是路径错误,这时候只要去Web.cofig配置文件中,配置一下,当出现404错误的时候,就跳转到我们自定义的错误页去)

[html] view plaincopy

  1. xml version="1.0" encoding="utf-8"?>  

  2.   

  3. <configuration>  

  4.   <system.web>  

  5.      

  6.       

  7.   

  8.       

  9.   

  10.       

  11.   

  12.       

  13.       

  14.         

  15.       

  16.       

  17.       

  18.       

  19.   

  20.     <customErrors mode="On" >  

  21.        <error statusCode="404" redirect="/Error/notfound"/>  

  22.     customErrors>  

  23.     

  24.   system.web>  

  25.    

  26. configuration>  


附赠logHelper.cs

[csharp] view plaincopy

  1. using System;  

  2. using System.Collections.Generic;  

  3. using System.Linq;  

  4. using System.Reflection;  

  5. using System.Text;  

  6. using System.Threading.Tasks;  

  7.   

  8. namespace Itcast.CMS.Common  

  9. {  

  10.     public class LogHelper  

  11.     {  

  12.         private log4net.ILog log = null;  

  13.         public LogHelper()  

  14.         {  

  15.             //如果Web.config配置文件中的key为log4net的value值为1,就表示log4net的配置文件是作为一个单独文件进行配置的,  

  16.             if (System.Configuration.ConfigurationManager.AppSettings["log4net"].ToString() == "1")  

  17.             {  

  18.                 //那么我就获取log4net的配置文件,并将它加载到我们的项目中去  

  19.                 string filePath = System.Configuration.ConfigurationManager.AppSettings["log4netPath"].ToString();  

  20.                 System.IO.FileInfo file = new System.IO.FileInfo(filePath);  

  21.   

  22.                 //Getlogger()静态方法,用来检索框架里是否存在logger对象,如果不存在就创建一个名字为logger的对象  

  23.                 log4net.Config.XmlConfigurator.Configure(file);  

  24.             }  

  25.             else  

  26.             {  

  27.                 log4net.Config.XmlConfigurator.Configure();  

  28.             }  

  29.             log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);  

  30.         }  

  31.         /// 

      

  32.         /// 程序运行的过程中的,一般信息可以调用此方法记录日记  

  33.         ///   

  34.         ///   

  35.         public void Info(string info)  

  36.         {  

  37.             if (log.IsInfoEnabled)  

  38.             {  

  39.                 log.Info(info);  

  40.             }  

  41.         }  

  42.         /// 

      

  43.         /// 程序运行的过程中的,一般信息可以调用此方法记录日记  

  44.         ///   

  45.         ///   

  46.         ///   

  47.         public void Info(string info, Exception ex)  

  48.         {  

  49.             if (log.IsInfoEnabled)  

  50.             {  

  51.                 log.Info(info, ex);  

  52.             }  

  53.         }  

  54.         /// 

      

  55.         /// 程序出现错误的时候调用此方法记录日记(一般用在出现了异常以后)  

  56.         ///   

  57.         ///   

  58.         public void Error(string info)  

  59.         {  

  60.             if (log.IsErrorEnabled)  

  61.             {  

  62.                 log.Error(info);  

  63.             }  

  64.         }  

  65.         /// 

      

  66.         ///  程序出现错误的时候调用此方法记录日记(一般用在出现了异常以后)  

  67.         ///   

  68.         ///   

  69.         ///   

  70.         public void Error(string info, Exception ex)  

  71.         {  

  72.             if (log.IsErrorEnabled)  

  73.             {  

  74.                 log.Error(info, ex);  

  75.             }  

  76.         }  

  77.         /// 

      

  78.         /// 程序员觉得任何有利于程序在调试时更详细的了解系统运行状态的信息,比如变量的值等等,都可以调用此方法记录到日记  

  79.         ///   

  80.         ///   

  81.         public void Debug(string info)  

  82.         {  

  83.             if (log.IsDebugEnabled)  

  84.             {  

  85.                 log.Debug(info);  

  86.             }  

  87.         }  

  88.         /// 

      

  89.         /// 程序员觉得任何有利于程序在调试时更详细的了解系统运行状态的信息,比如变量的值等等,都可以调用此方法记录到日记  

  90.         ///   

  91.         ///   

  92.         ///   

  93.         public void Debug(string info, Exception ex)  

  94.         {  

  95.             if (log.IsDebugEnabled)  

  96.             {  

  97.                 log.Debug(info, ex);  

  98.             }  

  99.         }  

  100.         /// 

      

  101.         /// 程序出现警告时调用此方法记录日记(程序出现警告不会使程序出现异常,但是可能会影响程序性能)  

  102.         ///   

  103.         ///   

  104.         public void Warn(string info)  

  105.         {  

  106.             if (log.IsWarnEnabled)  

  107.             {  

  108.                 log.Warn(info);  

  109.             }  

  110.         }  

  111.         /// 

      

  112.         ///  程序出现警告时调用此方法记录日记(程序出现警告不会使程序出现异常,但是可能会影响程序性能)  

  113.         ///   

  114.         ///   

  115.         ///   

  116.         public void Warn(string info, Exception ex)  

  117.         {  

  118.             if (log.IsWarnEnabled)  

  119.             {  

  120.                 log.Warn(info, ex);  

  121.             }  

  122.         }  

  123.         /// 

      

  124.         /// 程序出现特别严重的错误,一般是在应用程序崩溃的时候调用此方法记录日记  

  125.         ///   

  126.         ///   

  127.         public void Fatal(string info)  

  128.         {  

  129.             if (log.IsFatalEnabled)  

  130.             {  

  131.                 log.Fatal(info);  

  132.             }  

  133.         }  

  134.         /// 

      

  135.         /// 程序出现特别严重的错误,一般是在应用程序崩溃的时候调用此方法记录日记  

  136.         ///   

  137.         ///   

  138.         ///   

  139.         public void Fatal(string info, Exception ex)  

  140.         {  

  141.             if (log.IsFatalEnabled)  

  142.             {  

  143.                 log.Fatal(info, ex);  

  144.             }  

  145.         }  

  146.     }