目录
一:说明
IExceptionFilter同步过滤器与IAsyncExceptionFilter异步过滤器常常被用作于异常处理。
有异步方法则执行异步方法;没有异步方法执行同步方法。
IExceptionFilter异步过滤器执行顺序:
1:执行控制器中的构造函数,实例化控制器
2:执行具体的Action方法
3:执行ResultFilter.OnResultExecuting方法
4:渲染视图或处理结果
5:执行ResultFilter.OnResultExecuted方法
二:IAsyncExceptionFilter异步
控制器代码:
/// <summary>
/// Get请求
/// 应用ExceptionFilter扩展
/// Home控制器的Index
/// </summary>
/// <returns>Index视图</returns>
[HttpGet]
[ExceptionFilter]
public IActionResult Index()
{
throw new Exception("发生异常错误");
}
关键类ExceptionFilter代码:
using Microsoft.AspNetCore.Mvc.Filters;
namespace Study_ASP.NET_Core_MVC.Utility.Filters
{
public class ExceptionFilter : Attribute, IExceptionFilter, IAsyncExceptionFilter
{
/// <summary>
/// 当有异常发生时
/// </summary>
/// <param name="context"></param>
/// <exception cref="NotImplementedException"></exception>
public void OnException(ExceptionContext context)
{
throw new NotImplementedException();
}
/// <summary>
/// 当有异常发生时
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public Task OnExceptionAsync(ExceptionContext context)
{
throw new NotImplementedException();
}
}
}
三:标准异常处理IExceptionFilter
控制器代码:
/// <summary>
/// Get请求
/// 应用ExceptionFilter扩展
/// Home控制器的Index
/// </summary>
/// <returns>Index视图</returns>
[HttpGet]
[ExceptionFilter]
public IActionResult Index()
{
throw new Exception("发生异常错误");
}
关键ExceptionFilter类代码:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
namespace Study_ASP.NET_Core_MVC.Utility.Filters
{
public class ExceptionFilter : Attribute, IExceptionFilter
{
/// <summary>
/// 初始化IOC构造函数
/// </summary>
private readonly IModelMetadataProvider _IModelMetadataProvider;
public ExceptionFilter(IModelMetadataProvider modelMetadataProvider)
{
this._IModelMetadataProvider = modelMetadataProvider;
}
/// <summary>
/// 当有异常发生时
/// </summary>
/// <param name="context"></param>
/// <exception cref="NotImplementedException"></exception>
public void OnException(ExceptionContext context)
{
if(context.ExceptionHandled==false)
{
//判断是否时Ajax请求,返回Json格式数据
if (IsAjaxRequest(context.HttpContext.Request))
{
context.Result = new JsonResult(new
{
Success = false,
Message = context.Exception.Message
});
}
else
{
//返回错误视图
ViewResult result = new ViewResult { ViewName = "~/Views/Shared/Error.cshtml" };
result.ViewData = new ViewDataDictionary(_IModelMetadataProvider, context.ModelState);
result.ViewData.Add("Exception", context.Exception);
context.Result = result;
}
context.ExceptionHandled = true;
}
}
/// <summary>
/// 获取请求头是否包含X-Requested-With
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private bool IsAjaxRequest(HttpRequest request)
{
string header = request.Headers["X-Requested-With"];
return "XMLHttpRequest".Equals(header);
}
}
}
关键Error.cshtml文件代码:
@model ErrorViewModel
@{
ViewData["Title"] = "Error";
Exception exception = ViewData["Exception"] as Exception;
}
<h1 class="text-danger">错误页</h1>
<h2 class="text-danger">你的请求发生错误。</h2>
@if (exception!=null)
{
<h3 class="text-danger">错误信息:@exception.Message</h3>
}
结果截图:
四:异常处理的场景分析:
Action没有处理的异常:可以捕捉
Service层异常:可以捕捉
控制器构造函数异常:可以捕捉
ActionFilter异常:可以捕捉
Action已经处理的异常:不是异常
View绑定异常:不可以捕捉
错误Url地址异常:不可以捕捉
ResourceFilter异常:不可以捕捉
ResultFilter异常:不可以捕捉
五:通过中间件捕捉异常:
//异常处理中间件
{
//如果Http请求中的Response中的状态不是200,就会进入Home/Error中
app.UseStatusCodePagesWithReExecute("~/Views/Error/{0}");
//重写Response请求编码,错误页输出
app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
context.Response.StatusCode = 200;
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("<html lang=\"en\"><body>\r\n");
await context.Response.WriteAsync("Error!<br><br>\r\n");
var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
Console.WriteLine($"{exceptionHandlerPathFeature?.Error.Message}");
Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
{
await context.Response.WriteAsync("File Error Thrown!<br><br>\r\n");
}
await context.Response.WriteAsync("<a href=\"/\">Home</a><br>\r\n");
await context.Response.WriteAsync("</body></html>\r\n");
await context.Response.WriteAsync(new string(' ', 512));
});
});
}