2016-02-13 51 views
16

我有一个全球性的异常过滤器命名为LogErrorAttribute无论是全球的异常过滤器或Application_Error事件被捕获未处理的异常

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控制器,然后使用AutoMapper到模型映射到视图模型:

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把他们on
  2. 删除了HandleErrorAttribute全局过滤器,因为我意识到它设置了错误处理,如果它甚至运行。我不希望它执行任何操作,因为这个错误发生在控制器外面,但是它稍后可能会咬我。
+2

我讨厌成为“那家伙”,但你有没有试过清理(删除)bin和obj文件夹,然后清除网页浏览器缓存?似乎你正在做的一切正常(从最初的一瞥) – Pseudonym

+0

@别名我完全理解,但是,我一直在那条路上。 –

+0

好吧,我将不得不仔细阅读你的问题 – Pseudonym

回答

9

简短的回答是,你要添加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); 
    } 
} 

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

public static void Register(HttpConfiguration config) 
{ 

... 

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

} 
+0

我要给这个改变一个镜头。但是,即使这可以修复过滤器,为什么全局处理程序不会收集错误? –

+1

@MichaelPerrenoud,我加入到我的答案中。 jist是** HTTP Context **不同于** MVC context **。为什么会有相关的解释。解释它的最简单方法是** Web API **比完整的** MVC **框架轻得多的框架 –

+0

@DaveAlperovich - 我不知道你是如何得出这个结论的。OP没有给出他使用Web API的任何迹象,无论是问题本身还是标签。所以,因为他显然会尝试它,看起来你的假设是正确的。还有一种情况是有人错误地标记了他们的问题,因为这看起来与ASP.NET MVC毫无关系,ASP.NET MVC与Web API完全不同。我相信如果将这些信息包含在问题中,答案会更快。 – NightOwl888

0

戴夫Alperovich答案将通过HttpActionExecutedContext

public override void OnException(HttpActionExecutedContext context) 

但是解决你的问题,因为你想捕捉到你的应用程序可能在异常过滤器应使用消息处理程序产生,然后开所有可能的异常以及。详细的解释可以在这里找到 - http://www.asp.net/web-api/overview/error-handling/web-api-global-error-handling

总之,有很多情况下,异常过滤器无法处理。例如:

  • 控制器构造函数抛出的异常。
  • 消息处理程序抛出的异常。
  • 路由期间抛出的异常。
  • 例外响应内容序列化过程中引发

所以,如果从应用程序内的任何地方发生未处理的错误,异常处理程序将赶上它,并允许您采取具体行动

//Global exception handler that will be used to catch any error 
public class MyExceptionHandler : ExceptionHandler 
    { 
     private class ErrorInformation 
     { 
      public string Message { get; set; } 
      public DateTime ErrorDate { get; set; }    
     } 

     public override void Handle(ExceptionHandlerContext context) 
     { 
      context.Result = new ResponseMessageResult(context.Request.CreateResponse(HttpStatusCode.InternalServerError, 
       new ErrorInformation { Message="An unexpected error occured. Please try again later.", ErrorDate=DateTime.UtcNow })); 
     } 
    }