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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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 给注册进来。
1
2
3
4
5
6
|
private readonly ILogger<CustomExceptionFilterAttribute> _logger;
public CustomExceptionFilterAttribute(ILogger<CustomExceptionFilterAttribute> logger)
{
_logger = logger;
}
|
这时在 Action 有2中注册方式:
ServiceFilter 和 TypeFilter 区别在于 一个需要在 全局注册实现,一个不需要。使用 ServiceFilter 在Startup中注册一下
三、探究 ServiceFilter 和 TypeFilter 原理
我们看到 他们继承的都是一样的。主要是实现 CreateInstance 来获取实例对象。接下来我们模仿自定义一个
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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里面注入了。做了更多的事情。