簡體   English   中英

全局異常過濾器或Application_Error都不是捕獲未處理的異常

[英]Neither the Global Exception Filter or the Application_Error are Catching Unhandled Exceptions

我有一個名為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控制器,它從數據庫中獲取一些數據,然后使用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全局過濾器,因為我意識到它正在設置錯誤,如果它甚至在運行的話。 我不希望它仍然在執行,因為這個錯誤發生在控制器外部,但它可能會在稍后發生。

簡短的回答是您要添加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);
    }
}

另一個重要步驟是在Register(HttpConfiguration config)方法中在WebApiConfig.cs中Register(HttpConfiguration config) Global Web API異常過濾器。

public static void Register(HttpConfiguration config)
{

...

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

}

Dave 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 }));
        }
   }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM