ASP.NET MVC中的統一化自定義異常處理

使用系統默認的錯誤處理方式,能夠減小一次重定向訪問,而且正常提示了錯誤信息,併發送了錯誤碼500,但應注意如下問題:css

1、須要修改web.confightml

    <customErrors mode="On">
    </customErrors>
jquery

2、若是修改默認的Error.cshtml文件,不使用默認佈局頁或修改佈局頁,應引用下列文件web

    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
bootstrap

3、默認的HandleErrorAttribute只處理500錯誤,因此應重寫此類並加入過濾器。寫入日誌。服務器

HandleErrorAttribute源碼(可能與最新源碼不一致)併發

 

        public virtual void OnException(ExceptionContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }
            if (filterContext.IsChildAction)
            {
                return;
            }

            // If custom errors are disabled, we need to let the normal ASP.NET exception handler
            // execute so that the user can see useful debugging information.
            if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
            {
                return;
            }

            Exception exception = filterContext.Exception;

            // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method),
            // ignore it.
            if (new HttpException(null, exception).GetHttpCode() != 500)
            {
                return;
            }

            if (!ExceptionType.IsInstanceOfType(exception))
            {
                return;
            }

            string controllerName = (string)filterContext.RouteData.Values["controller"];
            string actionName = (string)filterContext.RouteData.Values["action"];
            HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
            filterContext.Result = new ViewResult
            {
                ViewName = View,
                MasterName = Master,
                ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
                TempData = filterContext.Controller.TempData
            };
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.Clear();
            filterContext.HttpContext.Response.StatusCode = 500;

            // Certain versions of IIS will sometimes use their own error page when
            // they detect a server error. Setting this property indicates that we
            // want it to try to render ASP.NET MVC's error page instead.
            filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
        }

 

 

若是不使用過濾器,參考下面內容app

 

===========================================================================================================================================asp.net

使用HandleErrorAttribute後,找到了Error.cshtml,則此時異常已經被捕獲處理,因此不會再次被Application_Error捕獲處理。佈局

因此啊,若是想使用Application_Error,就要

 

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            //filters.Add(new HandleErrorAttribute());
        }
    }

 

 

 

 

 

 

=======================================================================================================================================================================================

當ASP.NET MVC程序出現了異常,怎麼處理更加規範?

1. 最簡單的方法是設置<customErrors/>節點

<customErrors>節點用於定義一些自定義錯誤信息的信息。此節點有Mode和defaultRedirect兩個屬性,其中defaultRedirect屬性是一個可選屬性,表示應用程序發生錯誤時重定向到的默認URL,若是沒有指定該屬性則顯示通常性錯誤。Mode屬性是一個必選屬性,它有三個可能值,它們所表明的意義分別以下: On 表示在本地和遠程用戶都會看到自定義錯誤信息。 Off 禁用自定義錯誤信息,本地和遠程用戶都會看到詳細的錯誤信息。 RemoteOnly 表示本地用戶將看到詳細錯誤信息,而遠程用戶將會看到自定義錯誤信息。

這裏有必要說明一下本地用戶和遠程用戶的概念。當咱們訪問asp.net應用程時所使用的機器和發佈asp.net應用程序所使用的機器爲同一臺機器時成爲本地用戶,反之則稱之爲遠程用戶。在開發調試階段爲了便於查找錯誤Mode屬性建議設置爲Off,而在部署階段應將Mode屬性設置爲On或者RemoteOnly,以免這些詳細的錯誤信息暴露了程序代碼細節從而引來黑客的入侵。

<error>子節點

在<customErrors>節點下還包含有<error>子節點,這個節點主要是根據服務器的HTTP錯誤狀態代碼而重定向到咱們自定義的錯誤頁面,注意要使<error>子節點下的配置生效,必須將<customErrors>節點節點的Mode屬性設置爲「On」。下面是一個例子:

  1. <customErrors mode="On" defaultRedirect="GenericErrorPage.htm">   
  2.      <error statusCode="403" redirect="403.htm" />   
  3.      <error statusCode="404" redirect="404.htm" />   
  4. </customErrors>  
<customErrors mode="On" defaultRedirect="GenericErrorPage.htm"> 
     <error statusCode="403" redirect="403.htm" /> 
     <error statusCode="404" redirect="404.htm" /> 
</customErrors>

在上面的配置中若是用戶訪問的頁面不存在就會跳轉到404.htm頁面,若是用戶沒有權限訪問請求的頁面則會跳轉到403.htm頁面,403.htm和404.htm頁面都是咱們本身添加的頁面,咱們能夠在頁面中給出友好的錯誤提示。

 

2. 使用過濾器HandleErrorAttribute

隨着ASP.NET MVC版本的更新,出現了HandleErrorAttribute,使用Filter以AOP的思想實現了針對於Action的異常處理。使用此Filter後,當程序中出現異常的時候,會去封裝這些異常信息,而後路由自動轉到該Controller對應的Error.cshtml中,若是此路徑下沒有改文件,則會到shared目錄中尋找此文件。另一個相關的是在Global.asax中的protected void Application_Error(object sender, EventArgs e)方法,是捕捉異常的最後一道防線,也就是說,這是最高層次的異常捕獲處理邏輯。使用HandleErrorAttribute後,找到了Error.cshtml,則此時異常已經被捕獲處理,因此不會再次被Application_Error捕獲處理。此外,能夠經過@model HandleErrorInfo 在Error.cshtml中定製顯示異常信息。有一點須要注意的是,HandleErrorAttribute是在customErrors基礎之上的,若是想使用HandleErrorAttribute,customErrors的Mode必需要設置爲On或RemoteOnly.  不然,HandleErrorAttribute將不起做用。

3. 自定義顯示路徑

若是遇到異常後不僅僅是要自定義異常顯示,並且還須要進行日誌記錄。此時,能夠經過繼承擴展HandleErrorAttribute來實現新的Filter,而後在lobal.ascx中對全部的Action進行註冊,filters.Add(new MyHandleErrorAttribute()).在這裏詳細說明一下另外一種方式。咱們能夠寫一個專門的Controller和Action來進行異常發生時的路由設置.

[csharp] view plain copy print ?
  1. public class UtilityController : Controller  
  2.     {  
  3.         public ActionResult Error()  
  4.         {  
  5.             return View();  
  6.         }  
  7.   
  8.         public ActionResult PageNotFound()  
  9.         {  
  10.             return View();  
  11.         }  
  12. }  
public class UtilityController : Controller
    {
        public ActionResult Error()
        {
            return View();
        }

        public ActionResult PageNotFound()
        {
            return View();
        }
}

當出現異常的時候,把異常拋到最頂端,由Application_Error統一處理。這裏的統一處理就包括,記錄日誌,從新進行頁面定向等。

protected void Application_Error(object sender, EventArgs e)  
  1.         {  
  2.             var ex = Server.GetLastError();  
  3.             Log.Error(ex); //記錄日誌信息  
  4.             var httpStatusCode = (ex is HttpException) ? (ex as HttpException).GetHttpCode() : 500; //這裏僅僅區分兩種錯誤  
  5.             var httpContext = ((MvcApplication)sender).Context;  
  6.             httpContext.ClearError();  
  7.             httpContext.Response.Clear();  
  8.             httpContext.Response.StatusCode = httpStatusCode;  
  9.             var shouldHandleException = true;  
  10.             HandleErrorInfo errorModel;  
  11.   
  12.             var routeData = new RouteData();  
  13.             routeData.Values["controller"] = "Utility";  
  14.   
  15.             switch (httpStatusCode)  
  16.             {  
  17.                 case 404:  
  18.                     routeData.Values["action"] = "PageNotFound";  
  19.                     errorModel = new HandleErrorInfo(new Exception(string.Format("No page Found", httpContext.Request.UrlReferrer), ex), "Utility""PageNotFound");  
  20.                     break;  
  21.   
  22.                 default:  
  23.                     routeData.Values["action"] = "Error";  
  24.                     Exception exceptionToReplace = null//這裏使用了EntLib的異常處理模塊的一些功能  
  25.                     shouldHandleException = ExceptionPolicy.HandleException(ex, "LogAndReplace"out exceptionToReplace);  
  26.                     errorModel = new HandleErrorInfo(exceptionToReplace, "Utility""Error");  
  27.                     break;  
  28.             }  
  29.   
  30.             if (shouldHandleException)  
  31.             {  
  32.                 var controller = new UtilityController();  
  33.                 controller.ViewData.Model = errorModel; //經過代碼路由到指定的路徑  
  34.                 ((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));  
  35.             }  
  36.         }  
  37.     }  
相關文章
相關標籤/搜索