MVC 異常過濾器

本文實現對MVC異常處理功能,藉此來討論ASP.NET MVC中攔截器的使用方法。

第一步:寫一個自己的異常過濾器,讓它繼承HandleErrorAttribute類 然後重寫OnException()這個方法  (注:HandleErrorAttribute 類已經繼承了FilterAttribute, IExceptionFilter這兩個接口,並實現了它們,所以這我們只要繼承HandleErrorAttribute就可以了)

[csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片

  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在CODE上查看代碼片派生到我的代碼片

  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在CODE上查看代碼片派生到我的代碼片

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

  2.   

  3. <configuration>  

  4.   <system.web>  

  5.      

  6.     <!--定義友好的錯誤,出錯默認導向到 我們定義好的友好錯誤頁面 -->  

  7.   

  8.     <!--mode 屬性:mode="On"的時候就表示對所以訪問者都顯示定製錯誤頁;mode="Off"就表示關閉定製的錯誤頁,頁面錯誤的時候將本地和遠程用戶都會 看到詳細的錯誤信息;mode="RemoteOnly"就表示本地用戶將看到詳細錯誤信息(這裏的本地的意思即:你直接登陸網站服務器上),而遠程用戶 將會看到程序員定製的錯誤頁。所以一般情況下我們都建議將mode屬性設爲RemoteOnly-->  

  9.   

  10.     <!--RedirectMode 屬 性:獲取或設置一個值,該值指示在將用戶重定向到自定義錯誤頁面時,是否應更改請求的 URL。默認值爲 ResponseRedirect。如 果 RedirectMode 屬性設置爲 ResponseRedirect,則將用戶重定向到該錯誤頁面,並且原始 URL 更改爲該錯誤頁面 的 URL。如果 RedirectMode 屬性設置爲 ResponseRewrite,則將用戶定向到錯誤頁面,並且不更改瀏覽器中的原 始 URL。【ResponseRedirect其實就是Response.Redirect;而ResponseRewrite其實就是 Server.Transfer】 -->  

  11.   

  12.     <!--defaultRedirect屬性:應用程序在發生錯誤時重定向到的默認URL-->  

  13.     <!--<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="/Error/notfound">-->  

  14.         

  15.     <!--在它下面還可以分的很詳細,可以針對一些錯誤碼來指向我們針對這些錯誤碼而定製的頁面-->  

  16.     <!--<error statusCode="403" redirect="/Error/403" />-->  

  17.     <!--<error statusCode="404" redirect="/Error/404" />-->  

  18.     <!--</customErrors>-->  

  19.   

  20.     <customErrors mode="On" >  

  21.        <error statusCode="404" redirect="/Error/notfound"/><!--出現404錯誤的時候跳轉到Error控制器下的notfound方法-->  

  22.     </customErrors>  

  23.     

  24.   </system.web>  

  25.    

  26. </configuration>  


附贈logHelper.cs

[csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片

  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.         /// <summary>  

  32.         /// 程序運行的過程中的,一般信息可以調用此方法記錄日記  

  33.         /// </summary>  

  34.         /// <param name="info"></param>  

  35.         public void Info(string info)  

  36.         {  

  37.             if (log.IsInfoEnabled)  

  38.             {  

  39.                 log.Info(info);  

  40.             }  

  41.         }  

  42.         /// <summary>  

  43.         /// 程序運行的過程中的,一般信息可以調用此方法記錄日記  

  44.         /// </summary>  

  45.         /// <param name="info"></param>  

  46.         /// <param name="ex"></param>  

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

  48.         {  

  49.             if (log.IsInfoEnabled)  

  50.             {  

  51.                 log.Info(info, ex);  

  52.             }  

  53.         }  

  54.         /// <summary>  

  55.         /// 程序出現錯誤的時候調用此方法記錄日記(一般用在出現了異常以後)  

  56.         /// </summary>  

  57.         /// <param name="info"></param>  

  58.         public void Error(string info)  

  59.         {  

  60.             if (log.IsErrorEnabled)  

  61.             {  

  62.                 log.Error(info);  

  63.             }  

  64.         }  

  65.         /// <summary>  

  66.         ///  程序出現錯誤的時候調用此方法記錄日記(一般用在出現了異常以後)  

  67.         /// </summary>  

  68.         /// <param name="info"></param>  

  69.         /// <param name="ex"></param>  

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

  71.         {  

  72.             if (log.IsErrorEnabled)  

  73.             {  

  74.                 log.Error(info, ex);  

  75.             }  

  76.         }  

  77.         /// <summary>  

  78.         /// 程序員覺得任何有利於程序在調試時更詳細的瞭解系統運行狀態的信息,比如變量的值等等,都可以調用此方法記錄到日記  

  79.         /// </summary>  

  80.         /// <param name="info"></param>  

  81.         public void Debug(string info)  

  82.         {  

  83.             if (log.IsDebugEnabled)  

  84.             {  

  85.                 log.Debug(info);  

  86.             }  

  87.         }  

  88.         /// <summary>  

  89.         /// 程序員覺得任何有利於程序在調試時更詳細的瞭解系統運行狀態的信息,比如變量的值等等,都可以調用此方法記錄到日記  

  90.         /// </summary>  

  91.         /// <param name="info"></param>  

  92.         /// <param name="ex"></param>  

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

  94.         {  

  95.             if (log.IsDebugEnabled)  

  96.             {  

  97.                 log.Debug(info, ex);  

  98.             }  

  99.         }  

  100.         /// <summary>  

  101.         /// 程序出現警告時調用此方法記錄日記(程序出現警告不會使程序出現異常,但是可能會影響程序性能)  

  102.         /// </summary>  

  103.         /// <param name="info"></param>  

  104.         public void Warn(string info)  

  105.         {  

  106.             if (log.IsWarnEnabled)  

  107.             {  

  108.                 log.Warn(info);  

  109.             }  

  110.         }  

  111.         /// <summary>  

  112.         ///  程序出現警告時調用此方法記錄日記(程序出現警告不會使程序出現異常,但是可能會影響程序性能)  

  113.         /// </summary>  

  114.         /// <param name="info"></param>  

  115.         /// <param name="ex"></param>  

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

  117.         {  

  118.             if (log.IsWarnEnabled)  

  119.             {  

  120.                 log.Warn(info, ex);  

  121.             }  

  122.         }  

  123.         /// <summary>  

  124.         /// 程序出現特別嚴重的錯誤,一般是在應用程序崩潰的時候調用此方法記錄日記  

  125.         /// </summary>  

  126.         /// <param name="info"></param>  

  127.         public void Fatal(string info)  

  128.         {  

  129.             if (log.IsFatalEnabled)  

  130.             {  

  131.                 log.Fatal(info);  

  132.             }  

  133.         }  

  134.         /// <summary>  

  135.         /// 程序出現特別嚴重的錯誤,一般是在應用程序崩潰的時候調用此方法記錄日記  

  136.         /// </summary>  

  137.         /// <param name="info"></param>  

  138.         /// <param name="ex"></param>  

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

  140.         {  

  141.             if (log.IsFatalEnabled)  

  142.             {  

  143.                 log.Fatal(info, ex);  

  144.             }  

  145.         }  

  146.     }  



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章