前几天在webapi项目中遇到一个问题:Controller构造函数中抛出异常时全局过滤器捕获不到,于是网搜一把写下这篇博客作为总结。
HttpResponseException
通常在WebAPI的Controller中抛出的未处理异常,会以500的形式返回到客户端。而HttpResponseException
会返回我们指定的状态码,如返回501:
public HttpResponseMessage Exception() { //直接在Action中抛出HttpResponseException类型异常 throw new HttpResponseException(HttpStatusCode.NotImplemented); }
在抛出HttpResponseException
时,可将HttpResponseMessage类型的实例作为参数以提供给客户端更多的信息。
HttpError
public HttpResponseMessage Exception() { //使用Request对象创建返回到客户端的错误信息 Request.CreateErrorResponse() }
CreateErrorResponse
方法是HttpResponseMessage
类型的可扩展方法,该方法最终会调用扩展方法CreateResponse
返回一个HttpResponseMessage
类型的对象(ASP.NET WebAPI中Action的返回值最终都会被转换为HttpResponseMessage类型的对象),该对象包含一个HttpError
类型实例。
Exception Filters
自定义派生自ExceptionFilterAttribute或IExceptionFilter的异常处理类用于异常的处理。
过滤器可分为三个级别:
- Action
- Controller
- Global
注意:ASP.NET MVC和ASP.NET WebAPI的异常过滤器不可混用
ExceptionHandler
以下情形中的异常,过滤器是无法捕获到的:
-
Controller构造函数中抛出的异常
-
消息处理器中抛出的异常
-
路由过程中出现的异常
-
其它过滤器中抛出的异常
-
序列化返回内容时抛出的异常
解决方案如下:
自定义异常处理器,两种方式
public class XfhExceptionHandler : ExceptionHandler { public override void Handle(ExceptionHandlerContext context) { context.Result = new ResponseMessageResult( context.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "发生了不可描述的错误!") ); //new InternalServerErrorResult(context.Request); } }
替换ASP.NET WebAPI默认的异常处理器
public static void Register(HttpConfiguration config) { config.Services.Replace(typeof(IExceptionHandler), new XfhExceptionHandler()); }
PS:若要记录未处理异常日志可实现接口IExceptionLogger或继承ExceptionLogger
小结
IExceptionFilter只能处理Action中发生的未处理异常,IExceptionHandler可以处理任何地方发生的未处理异常。
相关阅读
catch all unhandled exceptions in ASP.NET Web Api
Handling Errors in Web API Using Exception Filters and Exception Handlers
Exception Handling in ASP.NET Web API
Global Error Handling in ASP.NET Web API 2
Action Results in Web API 2