ExceptionFilter 主要是為了捕捉系統異常。通常我們會繼承 ExceptionFilterAttribute ,實現自定義系統異常捕捉。 版本:.Net Core 3.1 一、基本創建過程 新建 .Net Core Mvc 並新建控制器 ExceptionFilterController ...
ExceptionFilter 主要是為了捕捉系統異常。通常我們會繼承 ExceptionFilterAttribute ,實現自定義系統異常捕捉。
版本:.Net Core 3.1
一、基本創建過程
- 新建 .Net Core Mvc 並新建控制器 ExceptionFilterController
-
Index 控制器肯定會報錯,這時候我們就要實現 CustomExceptionFilterAttribute 去捕捉系統異常。
public class CustomExceptionFilterAttribute : ExceptionFilterAttribute { public override void OnException(ExceptionContext context) { context.Result = new JsonResult(new { Result = false, Message = context.Exception.Message }); } }
F5 運行 可知 訪問 Index 異常可以正常能捕捉到了。
二、CustomExceptionFilterAttribute 優化
現在我們能夠捕捉到了異常。接下來我們可以把 CustomExceptionFilterAttribute 在優化一下。我們知道正常網站 可能是Ajax請求或是其他頁面請求。所以我們要根據請求類型返回不同的異常信息。比如 ajax 請求返回 json .其他返回 Error頁面。可惜的是.NET Core 正對 Request 沒有 擴展判斷是否是Ajax請求。我們看一下.NET Framework 是如何實現判斷Ajax請求的。
所以優化後 CustomExceptionFilterAttribute
public override void OnException(ExceptionContext context) { if (!context.ExceptionHandled) { if (context.HttpContext.Request.IsAjaxRequest()) { context.Result = new JsonResult(new { Result = false, Message = context.Exception.Message }); } else { context.Result = new RedirectResult("/Home/Error"); } context.ExceptionHandled = true; } }
現在想在 CustomExceptionFilterAttribute 使用文件記錄一些異常記錄,可以把 logger 給註冊進來。
private readonly ILogger<CustomExceptionFilterAttribute> _logger; public CustomExceptionFilterAttribute(ILogger<CustomExceptionFilterAttribute> logger) { _logger = logger; }
這時在 Action 有2中註冊方式:
ServiceFilter 和 TypeFilter 區別在於 一個需要在 全局註冊實現,一個不需要。使用 ServiceFilter 在Startup中註冊一下
三、探究 ServiceFilter 和 TypeFilter 原理
我們看到 他們繼承的都是一樣的。主要是實現 CreateInstance 來獲取實例對象。接下來我們模仿自定義一個
public class CustomServiceFilter : Attribute, IFilterFactory, IFilterMetadata { private readonly Type _FilterType = null; public CustomServiceFilter(Type type) { this._FilterType = type; } public bool IsReusable => true; public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) { return serviceProvider.GetService(this._FilterType) as IFilterMetadata; } }
其實發現 ServiceFilter 和 TypeFilter 無非就是 通過 serviceProvider 獲取了實例信息。只不過 TypeFilter 無需在 Startp裡面註入了。做了更多的事情。