MVC過濾器:自定義異常過濾器

1、異常過濾器

異常篩選器用於實現IExceptionFilter接口,並在ASP.NET MVC管道執行期間引起了未處理的異常時執行。異常篩選器可用於執行諸如日誌記錄或顯示錯誤頁之類的任務。HandleErrorAttribute類是異常篩選器的一個示例。html

先來看看HandleErrorAttribute類的定義:git

#region 程序集 System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// D:\Practice\MVC\自定義異常過濾器\MVCCuetomerExcepFilter\packages\Microsoft.AspNet.Mvc.5.2.7\lib\net45\System.Web.Mvc.dll
#endregion

namespace System.Web.Mvc
{
    //
    // 摘要:
    //     表示一個特性,該特性用於處理由操做方法引起的異常。
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class HandleErrorAttribute : FilterAttribute, IExceptionFilter
    {
        //
        // 摘要:
        //     初始化 System.Web.Mvc.HandleErrorAttribute 類的新實例。
        public HandleErrorAttribute();

        //
        // 摘要:
        //     獲取或設置異常的類型。
        //
        // 返回結果:
        //     異常的類型。
        public Type ExceptionType { get; set; }
        //
        // 摘要:
        //     獲取或設置用於顯示異常信息的母版視圖。
        //
        // 返回結果:
        //     母版視圖。
        public string Master { get; set; }
        //
        // 摘要:
        //     獲取此特性的惟一標識符。
        //
        // 返回結果:
        //     此特性的惟一標識符。
        public override object TypeId { get; }
        //
        // 摘要:
        //     獲取或設置用於顯示異常信息的頁視圖。
        //
        // 返回結果:
        //     頁視圖。
        public string View { get; set; }

        //
        // 摘要:
        //     在發生異常時調用。
        //
        // 參數:
        //   filterContext:
        //     操做篩選器上下文。
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     filterContext 參數爲 null。
        public virtual void OnException(ExceptionContext filterContext);
    }
}

 從代碼中能夠看出HandleErrorAttribute繼承了IExceptionFilter接口,而且有一個虛方法,若是要自定義異常過濾器,只須要繼承HandleErrorAttribute類並重寫HandleErrorAttribute類裏面的虛方法便可。github

2、示例

一、建立異常類

新建一個ExceptionFilters類繼承自HandleErrorAttribute,並重寫OnException方法,代碼以下:ide

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MVCCuetomerExcepFilter.Extension
{
    /// <summary>
    /// 異常過濾器
    /// </summary>
    public class ExceptionFilters : HandleErrorAttribute
    {
        /// <summary>
        /// 在異常發生時調用
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnException(ExceptionContext filterContext)
        {
            // 判斷是否已經處理過異常
            if(!filterContext.ExceptionHandled)
            {
                // 獲取出現異常的controller和action名稱,用於記錄
                string strControllerName = filterContext.RouteData.Values["controller"].ToString();
                string strActionName = filterContext.RouteData.Values["action"].ToString();
                // 定義一個HandleErrorInfo,用於Error視圖展現異常信息
                HandleErrorInfo info = new HandleErrorInfo(filterContext.Exception, strControllerName, strActionName);

                ViewResult result = new ViewResult
                {
                    ViewName = this.View,
                    // 定義ViewData,泛型
                    ViewData = new ViewDataDictionary<HandleErrorInfo>(info)
                };
                // 設置操做結果
                filterContext.Result = result;
                // 設置已經處理過異常
                filterContext.ExceptionHandled = true;
            }
            //base.OnException(filterContext);
        }
    }
}

二、建立控制器

新建一個控制器,代碼以下:測試

using MVCCuetomerExcepFilter.Extension;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MVCCuetomerExcepFilter.Controllers
{
    public class ExceptionController : Controller
    {
        // GET: Exception
        /// <summary>
        /// View表示發生異常時指定的視圖
        /// 這裏表示發生異常時使用ExceptionDetails視圖
        /// </summary>
        /// <returns></returns>
        [ExceptionFilters(View =("ExceptionDetails"))]
        public ActionResult Index()
        {
            // 測試拋出異常
            throw new NullReferenceException("測試拋出的異常");
        }
    }
}

 異常發生時使用ExceptionDetails視圖,因此在Shared文件夾裏面新建ExceptionDetails視圖,代碼以下:ui

<!--使用強類型視圖-->
@model System.Web.Mvc.HandleErrorInfo
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>異常</title>
</head>
<body>
    <p>
        拋錯控制器:<b>@Model.ControllerName</b> 拋錯方法:<b>@Model.ActionName</b> 拋錯類型:<b>
            @Model.Exception.GetType().Name
    </b>
</p>
<p>
    異常信息:<b>@Model.Exception.Message</b>
</p>
<p>
    堆棧信息:
</p>
<pre>@Model.Exception.StackTrace</pre>
</body>
</html>

 

3、測試

運行程序,訪問Exception控制器的Index方法,效果以下:this

4、總結

上面的案例演示了一個自定義異常類,很明顯比HandleError要靈活,在自定義異常類裏面能夠寫不少與業務相關的代碼。spa

GitHub代碼地址:git@github.com:JiangXiaoLiang1988/CustomerHandleErrorFilter.git日誌

相關文章
相關標籤/搜索