在我的 WebApi 2 项目中,我遵循服务模式以及工作单元和通用存储库模式。
所有控制器都有
try-catch
,以防万一某个操作没有,我有一个全局 IAutofacExceptionFilter
将捕获未处理的异常。
服务层也有异常处理。但是,存储库没有异常处理,因此异常会冒泡到他们遇到的第一个
try-catch
。
我还有一个自定义
DatabaseException
类,可以捕获 SaveChanges
上引发的 EF 数据库异常,并且效果很好。
但是,由于该项目目前正在大力开发,数据库更改与代码更改同时发生,因此诸如
SQLException
或 EntityCommandExecutionException
之类的异常情况很常见。我想捕获这些异常并抛出我自己的 DatabaseException
。
我应该在存储库级别、服务级别还是控制器级别捕获这些异常?
直接回答你的问题 - 我会在服务级别捕获异常,记录它们,然后重新抛出它们。
现在异常被重新抛出,应用程序也可以处理它,甚至再次记录它 - 这次是在调用控制器操作的上下文中。但是,例如,如果用户尝试保存一些数据并且失败了,那么在这种情况下失败的原因可能并不重要。因此捕获特定的异常类型可能没有多大帮助。 (可能吧。)
只有当应用程序要采取一些不同的操作来处理或解决异常时,捕获特定类型的异常才有真正的帮助,而这种情况并不常见。能够轻松访问日志并找到异常(任何异常)比将系统异常转换为自定义异常更有价值。
通常我的 MVC 应用程序中没有 try_catchs(不包括一两个现有的 try catch)
我所有的控制器都是继承自
BaseController
我有一个属性可以捕获应用程序中的所有异常:
public class HandleExceptionsAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
filterContext.Exception.InsertIntoDB(Membership.CurrentUserId, filterContext.RouteData.Values["controller"].ToString(), filterContext.RouteData.Values["action"].ToString());
}
}
[HandleExceptionsAttribute(View = "/Error/Index")]
public class BaseController : Controller
{
// Code...
}
在
HandleErrorAttribute
中,您甚至可以选择发生错误时要显示的页面。
如果您想过滤特定的异常:
if (filterContext.Exception is EntityCommandExecutionException)
// code
注意
要查看哪个操作和控制器发生异常,我获取当前控制器和当前操作并将其插入数据库。