c# - 全局异常过滤器或 Application_Error 都没有捕获未处理的异常

标签 c# asp.net-mvc asp.net-mvc-4 exception-handling automapper

我有一个名为 LogErrorAttribute 的全局异常过滤器:

public class LogErrorAttribute : IExceptionFilter
{
    private ILogUtils logUtils;

    public void OnException(ExceptionContext filterContext)
    {
        if (this.logUtils == null)
        {
            this.logUtils = StructureMapConfig.Container.GetInstance<ILogUtils>();
        }

        this.logUtils.LogError(HttpContext.Current.User.Identity.GetUserId(), "Unknown error.", filterContext.Exception);
    }
}

它与标准的 HandleErrorAttribute 过滤器一起注册:

filters.Add(new LogErrorAttribute());
filters.Add(new HandleErrorAttribute());

我正在像这样注册这些过滤器:

FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

我还有一个 Application_Error 回退:

protected void Application_Error()
{
    var exception = Server.GetLastError();
    Server.ClearError();
    var httpException = exception as HttpException;

    //Logging goes here

    var routeData = new RouteData();
    routeData.Values["controller"] = "Error";
    routeData.Values["action"] = "Index";

    if (httpException != null)
    {
        if (httpException.GetHttpCode() == 404)
        {
            routeData.Values["action"] = "NotFound";
        }
        Response.StatusCode = httpException.GetHttpCode();
    }
    else
    {
        Response.StatusCode = 500;
    }

    // Avoid IIS7 getting involved
    Response.TrySkipIisCustomErrors = true;

    // Execute the error controller
    if (exception != null)
    {
        this.errorLogger.Log(LogLevel.Error, "An unknown exception has occurred.", exception);
    }
    else if (httpException != null)
    {
        this.errorLogger.Log(LogLevel.Error, "An unknown HTTP exception has occurred.", httpException);
    }
    else
    {
        this.errorLogger.Log(LogLevel.Error, "An unknown error has occurred.");
    }
}

现在,我有一个 API Controller ,它从数据库中获取一些数据,然后使用 AutoMapper 将模型映射到 View 模型:

var viewModels = AutoMapper.Mapper.Map(users, new List<UserViewModel>());

AutoMapper 配置中,自定义解析器为其中一个属性执行:

var appModuleAssignments = this.appModuleAssignmentManager.Get(userId);
var appModules = appModuleAssignments.Select(x => this.appModuleManager.Get(x.AppModuleId));
return AutoMapper.Mapper.Map(appModules, new List<AppModuleViewModel>());

目前我正在强制 appModuleManager.Get 语句抛出一个常规异常:

throw new Exception("Testing global filter.");

这随后会在 AutoMapper 中抛出一个异常,这两个异常都未被处理,但是全局过滤器或 Application_Error 都没有发现这个异常。

我做错了什么?


发布后我做了一些事情:

  1. customErrors 属性添加到 Web.config 以将它们打开
  2. 删除了 HandleErrorAttribute 全局过滤器,因为我意识到即使它正在运行,它也会将错误设置为已处理。我不希望它无论如何都会执行,因为这个错误发生在 Controller 之外,但它可能会在以后影响我。

最佳答案

简短的回答是,您添加的是 MVC 异常过滤器,而不是 Web API 异常过滤器。

您的实现检查 ExceptionContext 而不是 HttpActionExecutedContext

public override void OnException(HttpActionExecutedContext actionExecutedContext)

由于框架将引发 Http 异常 而不是 MVC 异常,因此不会触发您的 OnException 覆盖方法。

那么,一个更完整的例子:

public class CustomExceptionFilter : ExceptionFilterAttribute

    {
       public override void OnException(HttpActionExecutedContext actionExecutedContext)

      {

        message = "Web API Error";
        status = HttpStatusCode.InternalServerError;

        actionExecutedContext.Response = new HttpResponseMessage()
        {
            Content = new StringContent(message, System.Text.Encoding.UTF8, "text/plain"),
            StatusCode = status
        };

        base.OnException(actionExecutedContext);
    }
}

另一个重要步骤是在 WebApiConfig.cs 中的 Register(HttpConfiguration config) 方法中注册您的全局 Web API 异常过滤器。

public static void Register(HttpConfiguration config)
{

...

config.Filters.Add(new CustomExceptionFilter());

}

关于c# - 全局异常过滤器或 Application_Error 都没有捕获未处理的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35382591/

相关文章:

c# - 有没有一种类型化的方法来在 C# 中声明方法名称

c# - Canvas 在新场景中加载后不会启用它

c# - 根据服务方法/Web API 请求验证 Blazor 中的字段

asp.net-mvc-4 - 使用 oauth 从外部登录服务(Gmail、facebook)注销

selectlist - asp.net MVC 4.0 下拉列表中的选定值

asp.net - 使用 SSL 在服务器上部署 ASP.Net MVC 5 应用程序

c# - 在 .Net Winforms 中使用打印预览

javascript - "Like"使用 Facebook 打开图的帖子

c# - ASP.NET MVC3、Razor - 在 Javascript 中使用 ViewBag 或 URL 变量

jquery - asp.net mvc textarea 与 jQuery 中换行符的字符计数