溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

ASP.NET MVC中異常處理和自定義錯誤頁的示例分析

發(fā)布時間:2021-07-12 14:41:23 來源:億速云 閱讀:112 作者:小新 欄目:開發(fā)技術(shù)

小編給大家分享一下ASP.NET MVC中異常處理和自定義錯誤頁的示例分析,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

一、應(yīng)用場景

對于B/S應(yīng)用程序,在部署到正式環(huán)境運行的過程中,很有可能出現(xiàn)一些在前期測試過程中沒有發(fā)現(xiàn)的一些異?;蛘咤e誤,或者說只有在特定條件滿足時才會發(fā)生的一些異常,對于使用ASP.NET MVC開發(fā)的應(yīng)用程序站點,在部署到IIS上后,如果開發(fā)人員未對程序進行錯誤處理,那么一旦程序出現(xiàn)未處理的錯誤或異常,用戶將看到一個讓人感到及其困惑的錯誤堆棧跟蹤頁面,使得站點的用戶體驗下降,從程序的角度上來說,不做自定義錯誤處理也不利于程序出問題時的根源查找,因為很多時候有些錯誤只在特定條件下滿足時才重現(xiàn),一旦錯過,可能就需要花大量時間去測試來重現(xiàn)問題,如果此時開發(fā)人員有對程序中的運行時異常進行日志記錄,那么或許將提供一些有價值的錯誤根源信息,下面我將向下大家講解如何實現(xiàn)自定義異常處理并跳轉(zhuǎn)到友好的錯誤提示頁面。

二、異常處理&自定義錯誤頁

1、通過異常過濾器 實現(xiàn)異常處理和自定義錯誤頁

asp.net mvc 提供了 異常過濾器 的方式來實現(xiàn)當執(zhí)行controller中某個action方法時拋出了未處理的異常時的捕捉,mvc中的異常過濾器是以特性(Attribute)的形式存在的,定義一個自定義異常過濾器只需要兩個步驟:

1、定義一個類,繼承FilterAttribute類,并實現(xiàn)IExceptionFilter接口 2、應(yīng)用自定義異常過濾器至指定的 action方法 或 controller類 或 全局應(yīng)用。

異常過濾器代碼

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

namespace Blog20180413.Filters
{
 public class CustomExceptionFilterAttribute : FilterAttribute, IExceptionFilter
 {
 //log4net組件,用于日志記錄。
 static readonly ILog log = LogManager.GetLogger(typeof(CustomExceptionFilterAttribute));
 public void OnException(ExceptionContext filterContext)
 {
  //對捕獲到的異常信息進行日志記錄,方便開發(fā)人員排查問題。
  log.Error("應(yīng)用程序異常", filterContext.Exception);

  //跳轉(zhuǎn)到自定義的錯誤頁,增強用戶體驗。
  ActionResult result = new ViewResult() { ViewName = "CustomErrorPage" };
  filterContext.Result = result;
  //異常處理結(jié)束后,一定要將ExceptionHandled設(shè)置為true,否則仍然會繼續(xù)拋出錯誤。
  filterContext.ExceptionHandled = true;
 }
 }
}

使用異常過濾器

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

namespace Blog20180413.Controllers
{
 public class TestExceptionHandleController : Controller
 {
 [CustomExceptionFilter]
 public ActionResult Index()
 {
  string str = string.Empty;
  //將拋出轉(zhuǎn)換異常
  int result = int.Parse(str);
  return View();
 }
 }
}

注意:

第二個步驟中提到,可以將自定義異常過濾器 只應(yīng)用到 action或者controller,如果只想將指定的異常過濾器以特性的形式應(yīng)用到指定的一個或者多個controller或者action,而不想應(yīng)用到所有的controller或者action,那么必須將該異常過濾器繼承FilterAttribute類,這是因為mvc框架是通過FilterAttributeFilterProvider.GetFilters來獲取標記在指定controller或者action上的異常過濾器特性的,而GetFilters內(nèi)部邏輯要求必須繼承自FilterAttribute類。

如果需要將自定義的異常過濾器應(yīng)用到所有的controller的action上,那么需要將該自定義異常過濾器注冊到全局,代碼如下:

using Blog20180413.Filters;
using System.Web;
using System.Web.Mvc;

namespace Blog20180413
{
 public class FilterConfig
 {
 public static void RegisterGlobalFilters(GlobalFilterCollection filters)
 {
  filters.Add(new CustomExceptionFilterAttribute());
 }
 }
}

2、通過在Global.asax 中定義Application_Error方法 實現(xiàn)異常處理和自定義錯誤頁

上面提到的 自定義異常過濾器只能捕獲在執(zhí)行action方法過程中拋出的異常(即使注冊為全局過濾器也只能捕獲action方法執(zhí)行過程中拋出的異常),如果需要捕獲更高級別的異常,也就是在請求執(zhí)行過程中出現(xiàn)的任何異常(如在控制器的構(gòu)造函數(shù)中拋出異常),那么可以使用該種方式,代碼如下:

using log4net;
using log4net.Config;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace Blog20180413
{
 public class MvcApplication : System.Web.HttpApplication
 {
  static readonly ILog log = LogManager.GetLogger(typeof(MvcApplication));
  protected void Application_Start()
  {
   AreaRegistration.RegisterAllAreas();
   FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
   RouteConfig.RegisterRoutes(RouteTable.Routes);
   XmlConfigurator.ConfigureAndWatch(new FileInfo(Server.MapPath("~/web.config")));
  }

  protected void Application_Error(object sender, EventArgs e)
  {
   Exception exception = Server.GetLastError();
   //Server.ClearError();
   //這里記錄錯誤日志信息
   log.Error("MvcApplication 捕獲異常", exception);
   //跳轉(zhuǎn)到指定的自定義錯誤頁
   Response.Redirect("/CustomErrorHandle/CustomErrorPage");
  }
 }
}

3、通過配置system.web->customErrors節(jié)點 實現(xiàn)自定義錯誤頁

當你的站點發(fā)生異常時,如果你只是想簡單的跳轉(zhuǎn)到一個自定義錯誤頁面,而不是對異常進一步處理時,那么你可以簡單的作如下配置操作即可:

需要在web.config中做如下配置:

 <system.web>
  <customErrors mode="On" defaultRedirect="CustomErrorPage">
  </customErrors>
 </system.web>

注意:這里的CustomErrorPage是一個視圖文件,放在Shared共享目錄下。

如果你注冊了HandleErrorAttribute異常過濾器到全局,那么在你的錯誤頁中將能獲取到和異常相關(guān)的一些信息。但此時配置到defaultRedirect的值的必須是Error

也就是自定義錯誤視圖頁面的名稱必須為Error.cshtml,并且放在Shared目錄,當然,你也可以通過在創(chuàng)建HandleErrorAttribute全局過濾器的過程中,設(shè)置器View屬性,這樣你就可以不用講錯誤視圖的名稱設(shè)置為Error了.如下:

 public static void RegisterGlobalFilters(GlobalFilterCollection filters)
 {
    HandleErrorAttribute errorAttribute = new HandleErrorAttribute();
    errorAttribute.View = "CustomErrorPage";
    filters.Add(errorAttribute);
 }

注冊HandleErrorAttribute(使用默認的錯誤視圖頁面文件名)

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

定義Error.cshtml視圖頁

@{
 Layout = null;
}
@model HandleErrorInfo
<!DOCTYPE html>
<html>
<head>
 <meta name="viewport" content="width=device-width" />
 <title>Error</title>
</head>
<body>
 <div>
  @*通過HandleErrorAttribute異常過濾器捕獲到的異常信息存儲在Model屬性中*@
  @Model.Exception.Message
 </div>
</body>
</html>

之所以通過注冊HandleErrorAttribute過濾器捕獲的異常在錯誤頁中能獲取異常信息可以看HandleErrorAttribute類的內(nèi)部實現(xiàn),發(fā)現(xiàn)加載錯誤視圖頁面的過程中,傳遞了一個HandleErrorInfo對象過去。

public virtual void OnException(ExceptionContext filterContext)
{
 if (filterContext == null)
 {
  throw new ArgumentNullException("filterContext");
 }
 if (!filterContext.IsChildAction && (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled))
 {
  Exception innerException = filterContext.Exception;
  if ((new HttpException(null, innerException).GetHttpCode() == 500) && this.ExceptionType.IsInstanceOfType(innerException))
  {
   string controllerName = (string) filterContext.RouteData.Values["controller"];
   string actionName = (string) filterContext.RouteData.Values["action"];
   HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
   ViewResult result = new ViewResult {
    ViewName = this.View,
    MasterName = this.Master,
    ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
    TempData = filterContext.Controller.TempData
   };
   filterContext.Result = result;
   filterContext.ExceptionHandled = true;
   filterContext.HttpContext.Response.Clear();
   filterContext.HttpContext.Response.StatusCode = 500;
   filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
  }
 }
}
public string View
{
 get
 {
  if (string.IsNullOrEmpty(this._view))
  {
   return "Error";
  }
  return this._view;
 }
 set => 
  (this._view = value);
}

看完了這篇文章,相信你對“ASP.NET MVC中異常處理和自定義錯誤頁的示例分析”有了一定的了解,如果想了解更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI