天天看點

說一說MVC的CustomHandlerErrorAttribute(五)

九月第一篇,呵呵

前言:最近剛入職了一家公司,上司讓我維護一個項目,我接手了看了一下項目,try catch 嚴重影響我的視覺,我直接通過vs插件将其try catch全部替換掉占位符,呵呵。

  是以我特此寫了這篇文章...

正本:有可能你在搞開發的時候在每個子產品中都要try catch,這樣不僅不優雅也非常累,看了這篇文章,你會有所收獲,你将會從50行代碼收縮成30行.當然這取決于你的邏輯。

在CustomHandlerErrorAttribute中要繼承HandleErrorAttribute

HandleErrorAttribute.cs

#region 程式集 System.Web.Mvc, Version=5.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
#endregion

namespace System.Web.Mvc
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class HandleErrorAttribute : FilterAttribute, IExceptionFilter
    {
        public HandleErrorAttribute();
        public Type ExceptionType { get; set; }
        public string Master { get; set; }
        public override object TypeId { get; }
        public string View { get; set; }
        public virtual void OnException(ExceptionContext filterContext);
    }
}      

人們常說虛方法都是可以重寫的,也就是說你可以去擴充它.看代碼CustomHandlerErrorAttribute.cs

說一說MVC的CustomHandlerErrorAttribute(五)

 為什麼我在這裡截圖呢,我是害怕别人複制黏貼,當然這不是我小氣,因為很多人百度 都太懶了,也希望你們尊重部落客的勞動成功

這樣隻要程式抛出異常,或者錯誤就換到自定義錯誤過濾器,這種形式也可以叫做短路器,當然不隻是包括action的行為,如果是ajax請求報錯,我們直接傳回json,例如伺服器崩掉。我們看一下測試過程。為了測試友善我直接把IIS啟動起來了。

我們先看一下最簡單的出錯:

public ActionResult ExceptionUnCatch()
{
  throw new Exception("ExceptionCatch");
  return View();
}      
@{
    ViewBag.Title = "ExceptionUnCatch";
}

<h2>ExceptionUnCatch</h2>      

結果

說一說MVC的CustomHandlerErrorAttribute(五)

經過測試也是成功跳入我的自定義錯誤過濾器,通過給action添加特性,才會使ASP.NET MVC 的生命周期中包括了我的過濾器。但是我們看另一種情況.我們加上try catch 呢?

public ActionResult ExceptionCatch()
        {
            try
            {
                throw new Exception("ExceptionCatch...");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return View();
        }      

視圖方面:

@{
    ViewBag.Title = "ExceptionCatch";
}

<h2>ExceptionCatch</h2>      
說一說MVC的CustomHandlerErrorAttribute(五)

 可以發現錯誤被catch掉了,那如果我們在頁面中抛出了異常呢.我們不去說view中會出什麼異常,直接在代碼中添加代碼塊<h1>@{throw new Exception("Exception View");}</h1>,經過我的測試,它也是成功的傳回錯誤資訊。

說一說MVC的CustomHandlerErrorAttribute(五)

自習看過我的代碼你會發現我在過濾器中添加了一個ajax請求的異常處理,我們簡單的測試一下.在視圖上定義了一個action  裡面指向參數   我并沒有那些控制器或action!!<h1>@Html.ActionLink("asdsa","asdsa")</h1>

結果   

說一說MVC的CustomHandlerErrorAttribute(五)

最後在FilterConfig.cs中對所有action生效

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            //filters.Add(new CustomAuthorizeAttribute());//3 全局注冊,全部的控制器/action都生效
            filters.Add(new CustomHandlerErrorAttribute());//
        }      

 但是處理不到的情況就有了,例如在控制器構造函數中抛出異常或者說通路的url不存在

說一說MVC的CustomHandlerErrorAttribute(五)

總來來說是因為它們是管道級别錯誤,不屬于acton行為級别 ,這種情況我們隻能借助配置項來對錯誤進行封裝

在system.web中添加

<customErrors mode="On" defaultRedirect="~/Demo.html">
      <error statusCode="404" redirect="~/Demo.html"/>
    </customErrors>      

另一種方式可以在global.asax.cs中添加Application.error或許你應該懂了吧?

protected void Application_Error(object sender,EventArgs args)
{
     var errorDetail = Server.GetLastError();
     Context.Response.Write(errorDetail);
     Server.ClearError();
}      

總結:使用自定義錯誤過濾器配合全局錯誤就可以達到非常好的錯誤處理。