ASP.NET MVC中錯誤處理方式


aspnet mvc的錯誤處理方式主要有以下兩種

方式一:通過對controller或者action標記HandleError屬性,然后指定一個錯誤頁即可。這種方式最簡單,不需要額外增加action ,僅僅需要增加錯誤頁,但是不能記錄日志(因為沒有action,其實在aspx中也可調用記錄日志的方法)。這個錯誤頁還可以定義為強類型,類型為HandleErrorInfo,具體的Model又框架傳遞,可獲取具體的異常信息。

HandlError 

/// <summary>
        /// 標記了HandleError,並指明錯誤處理頁為AboutError.aspx
        /// </summary>
        /// <returns></returns>
        [HandleError(View = "AboutError")]
        public ActionResult About()
        {
            return View();
        } 
AboutError.aspx 

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<HandleErrorInfo>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    AboutError
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    通過強類型獲取異常信息
    <%= Model.Exception.Message %>
</asp:Content>

這種方式比較靈活,比如需要對某個action定義個錯誤頁,就可采用這種方式。不過會有個小問題,后面會提到。

 

方式二:重寫controller類的onException方式,這種方式最直接了,通常用於一個項目的BaseController中,那么以后的controller都繼承這個類即可,可以在cs代碼中記錄錯誤日志,但是要定義錯誤頁的action和具體的錯誤頁面。方法中需要設置ExceptionHandled=true,否則錯誤會被拋到外層,這時候只能通過傳統的aspnet錯誤方式處理了,通常是招CustomerError中配置的錯誤頁,如果沒有配置,那就出現一個大黃頁了。ExceptionHandled=true這個操作會是邏輯有微妙的變化,后續提到。

重寫OnException 

 protected override void OnException(ExceptionContext filterContext)
        {
            // 標記異常已處理
            filterContext.ExceptionHandled = true;
            // 跳轉到錯誤頁
            filterContext.Result = new RedirectResult(Url.Action("Error", "Shared"));
        }

  講了這兩種方式,主要是為了講這兩種方式混用時會出現的問題。如果以action標記了HandleError屬性,同時期所在的controller又重寫了OnException方法,最終會怎樣處理呢?按照mvc中filter的執行順序,controller重寫的方法會被優先執行,不考慮action中的order順序,執行完畢之后再執行action標記的filter的方法。ok,有了這個理論之后,再看看之前提到的情況的執行順序。首先執行OnException中的處理方式,這時候filterContext.ExceptionHandled已經被標記為true了,再執行HandleError屬性的方法時,就不會在被執行了,也就是說自定義的錯誤頁白費了,不起作用。這是因為內置的HandleError在執行的時候會先判斷filterContext.ExceptionHandled是否為true,為true就不執行了,因此會出現一些很奇怪的bug,明白這個道理就知道如何處理了。

       但是總不能把filterContext.ExceptionHandled = true;這行代碼去掉,因為其他action沒有標記handle error屬性,如果不使filterContext.ExceptionHandled為true, 那么錯誤還是會拋到外層,又交給CustomerError處理了,還是白搭。因此既要保持基類的OnException方法,又要有action自己個性化的錯誤頁,是不能使用系統內置的方式處理,只能自己再去定義ExceptionFilter 了,就是方式三。

 方式三,自定義ExceptionFilter,需要繼承FilterAttribute,和實現IExceptionFilter接口,實現中不需要判斷Exception是否已處理,但要注意需要有AboutError這個action。

 

自定義ExceptionFilter

    public class AboutErrorAttribute : FilterAttribute, IExceptionFilter
    {
        #region IExceptionFilter 成員

        public void OnException(ExceptionContext filterContext)
        {
            UrlHelper url = new UrlHelper(filterContext.RequestContext);
            filterContext.Result = new RedirectResult(url.Action("AboutError", "AboutError"));
        }

        #endregion
    }

 

那么action中需要改成

 

/// <summary>
        /// 標記自定義的AboutError
        /// </summary>
        /// <returns></returns>
        [AboutError]
        public ActionResult About()
        {
            return View();
        }

 

經過一輪折騰,總算實現了需求,即保證了通用異常被正常處理,個別action個性化的錯誤頁面也能實現,還算比較整潔。但最好框架的HandleError能夠提供是否忽略判斷異常是否已被處理過的屬性設置。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM