当我的基本控制器的构造函数中调用的方法抛出错误时,不会触发全局应用的自定义异常过滤器
Globally applied custom exception filter is not triggered when error is thrown by a method called in the constructor of my base controller
我有这个自定义异常过滤器:
public class CustomExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
try
{
if (filterContext == null) return;
// Log error details to the DB
}
catch
{
// Intentional empty catch
}
}
}
在 RegisterGlobalFilters 中全局应用(从 Application_Start 调用):
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CustomExceptionFilter());
filters.Add(new HandleErrorAttribute());
}
然后我的 BaseController 上有一个受保护的构造函数调用此方法:
public Site GetSiteByUrl(string host)
{
var urls = _repo.Urls.Where(x => x.Host == host);
if (urls == null || !urls.Any())
throw new MultiTenancyException(String.Format("No URL record exists for request. Host = \"{0}\"", host));
if (urls.Count() > 1)
throw new MultiTenancyException(String.Format("Multiple URL records exist for request. Host = \"{0}\"",
host));
var url = urls.Single();
var site = _repo.Sites.Single(x => x.Id == url.SiteId);
if (!url.Enabled)
throw new MultiTenancyException(
String.Format("URL record found for request, but is not Enabled. Host = \"{0}\", Site = \"{1}\"",
host, site.Name));
return site;
}
当抛出此方法中的任何 MultiTenancyExceptions 时,不会触发我的 CustomExceptionFilter 的 OnException 事件。
我试过:
- 使用基本异常而不是我的自定义 MultiTenancyException。
- 将 CustomExceptionFilter 作为属性应用到控制器上,而不是通过 RegisterGlobalFilters 全局应用。
两者都无济于事。回顾 CustomExceptionFilter 捕获的异常日志,唯一记录的错误似乎是由系统异常(NullReference、ArgumentOutOfRange 等)引起的,这可能是相关的,也可能只是巧合。
我已经在谷歌上搜索了大约 30 分钟,此时我开始摸不着头脑,所以我正在寻找任何明智的想法。
谢谢。
来自 GlobalFilterCollection 的过滤器仅适用于控制器操作执行时发生的异常。
要捕获在操作执行之前或之后发生的异常,您应该在 Global.asax 文件中定义 Application_Error
方法:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
void Application_Error(object sender, EventArgs e)
{
// handle global errors here
}
}
我有这个自定义异常过滤器:
public class CustomExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
try
{
if (filterContext == null) return;
// Log error details to the DB
}
catch
{
// Intentional empty catch
}
}
}
在 RegisterGlobalFilters 中全局应用(从 Application_Start 调用):
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CustomExceptionFilter());
filters.Add(new HandleErrorAttribute());
}
然后我的 BaseController 上有一个受保护的构造函数调用此方法:
public Site GetSiteByUrl(string host)
{
var urls = _repo.Urls.Where(x => x.Host == host);
if (urls == null || !urls.Any())
throw new MultiTenancyException(String.Format("No URL record exists for request. Host = \"{0}\"", host));
if (urls.Count() > 1)
throw new MultiTenancyException(String.Format("Multiple URL records exist for request. Host = \"{0}\"",
host));
var url = urls.Single();
var site = _repo.Sites.Single(x => x.Id == url.SiteId);
if (!url.Enabled)
throw new MultiTenancyException(
String.Format("URL record found for request, but is not Enabled. Host = \"{0}\", Site = \"{1}\"",
host, site.Name));
return site;
}
当抛出此方法中的任何 MultiTenancyExceptions 时,不会触发我的 CustomExceptionFilter 的 OnException 事件。
我试过:
- 使用基本异常而不是我的自定义 MultiTenancyException。
- 将 CustomExceptionFilter 作为属性应用到控制器上,而不是通过 RegisterGlobalFilters 全局应用。
两者都无济于事。回顾 CustomExceptionFilter 捕获的异常日志,唯一记录的错误似乎是由系统异常(NullReference、ArgumentOutOfRange 等)引起的,这可能是相关的,也可能只是巧合。
我已经在谷歌上搜索了大约 30 分钟,此时我开始摸不着头脑,所以我正在寻找任何明智的想法。
谢谢。
来自 GlobalFilterCollection 的过滤器仅适用于控制器操作执行时发生的异常。
要捕获在操作执行之前或之后发生的异常,您应该在 Global.asax 文件中定义 Application_Error
方法:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
void Application_Error(object sender, EventArgs e)
{
// handle global errors here
}
}