ExceptionFilterAttribute 不处理属性异常
ExceptionFilterAttribute not handling properties exceptions
我实现了一个 ExceptionFilterAttribute class 并在 WebApiConfig class 中注册了它。
动作过滤器工作良好并处理任何动作中发生的任何异常,但问题是:当在任何控制器属性中发生异常时,动作过滤器不处理此异常
[NotImplExceptionFilterAttribute]
public class AnyController : APIController
{
private readonly ModelDBContext _db = new ModelDBContext();
//some actions
}
在上述例子中,ModelDBContext的构造函数中包含了一些可能导致异常的逻辑。 ExceptionFilterAttribute 不会处理此异常。为什么???以及如何处理?
基本上,简单的答案很简单:异常过滤器是动作级过滤器。
先看这张图:http://blogs.msdn.com/b/kiranchalla/archive/2012/05/06/asp-net-mvc4-web-api-stack-diagram-currently-in-development.aspx
然后导航到 ApiController, line #232. There you can see that if there is at least one filter then ExceptionFilterResult 将用于包装最终操作结果。
在 ExceptionFilterResult 内部有简单的 try-catch,如果抛出异常则调用所有已注册的异常过滤器。
所以,上面写的所有内容的简短摘要:
1)异常过滤器不负责处理控制器动作之上的错误
2) 当控制器的实例由 DI 容器创建并且当您的 ModelDBContext 抛出异常时异常过滤器不存在
我希望这能回答你的问题。
问题是范围。
当控制器被实例化时,private class member _db
将在任何 class 方法执行之前初始化。这是 CLR 行为。
因此,操作过滤器不会捕获在控制器对象 construction/initialization 期间发生的异常,例如未能构建 ModelDBContext
实例。
一个解决方案是在每个请求上创建和处理 ModelDBContext
个实例,如果您打算优雅地处理(或记录)连接失败(无论是到数据库或后端服务。)
您可能还会发现 IServiceLocator
和 'Unity' 或 'Ninject' 等框架很有用,这样您就不会到处都是 "hardcoding" new ModelDBContext();
语句,但那是另一个话题。根本原因是您在操作方法的范围之外进行初始化,操作过滤器不会捕获它。
我实现了一个 ExceptionFilterAttribute class 并在 WebApiConfig class 中注册了它。 动作过滤器工作良好并处理任何动作中发生的任何异常,但问题是:当在任何控制器属性中发生异常时,动作过滤器不处理此异常
[NotImplExceptionFilterAttribute]
public class AnyController : APIController
{
private readonly ModelDBContext _db = new ModelDBContext();
//some actions
}
在上述例子中,ModelDBContext的构造函数中包含了一些可能导致异常的逻辑。 ExceptionFilterAttribute 不会处理此异常。为什么???以及如何处理?
基本上,简单的答案很简单:异常过滤器是动作级过滤器。
先看这张图:http://blogs.msdn.com/b/kiranchalla/archive/2012/05/06/asp-net-mvc4-web-api-stack-diagram-currently-in-development.aspx 然后导航到 ApiController, line #232. There you can see that if there is at least one filter then ExceptionFilterResult 将用于包装最终操作结果。 在 ExceptionFilterResult 内部有简单的 try-catch,如果抛出异常则调用所有已注册的异常过滤器。 所以,上面写的所有内容的简短摘要: 1)异常过滤器不负责处理控制器动作之上的错误 2) 当控制器的实例由 DI 容器创建并且当您的 ModelDBContext 抛出异常时异常过滤器不存在
我希望这能回答你的问题。
问题是范围。
当控制器被实例化时,private class member _db
将在任何 class 方法执行之前初始化。这是 CLR 行为。
因此,操作过滤器不会捕获在控制器对象 construction/initialization 期间发生的异常,例如未能构建 ModelDBContext
实例。
一个解决方案是在每个请求上创建和处理 ModelDBContext
个实例,如果您打算优雅地处理(或记录)连接失败(无论是到数据库或后端服务。)
您可能还会发现 IServiceLocator
和 'Unity' 或 'Ninject' 等框架很有用,这样您就不会到处都是 "hardcoding" new ModelDBContext();
语句,但那是另一个话题。根本原因是您在操作方法的范围之外进行初始化,操作过滤器不会捕获它。