2016-02-13 13 views
16

Mam globalny filtr wyjątek nazwany LogErrorAttribute:Ani Globalne Filtr Wyjątek lub Application_Error są Catching nieobsługiwany wyjątków

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

Jest zarejestrowany wraz ze standardowym HandleErrorAttribute Filtr:

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

jestem rejestrowanie filtrów takich jak to:

FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 

Mam też Application_Error fallback:

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."); 
    } 
} 

Teraz mam kontroler interfejsu API, które chwyta niektóre dane z bazy danych, a następnie używa AutoMapper mapowanie modeli aby zobaczyć modele:

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

Wewnątrz że AutoMapper konfiguracja zwyczaj rezolwer wykonuje dla jednej z właściwości:

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

w tej chwili jestem zmuszając appModuleManager.Get oświadczenie rzucić regularny wyjątek:

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

ten następnie zgłasza wyjątek w AutoMapper, z których oba są nieobsługiwany jednak ani filtr globalny lub tym Application_Error odbierają ten wyjątek.

Co zrobiłem źle tutaj?


parę rzeczy zrobiłem od opublikowania:

  1. Dodany atrybut do Web.configcustomErrors je on obracać.
  2. Usunięto filtr globalny HandleErrorAttribute, ponieważ zdałem sobie sprawę, że ustawił błąd w obsłudze, nawet jeśli był uruchomiony. Nie spodziewałbym się, że tak się stanie, ponieważ ten błąd występuje poza kontrolerem, ale prawdopodobnie przydałoby mi się to później.
+2

Nienawidzę być "tym facetem", ale czy próbowałeś wyczyścić (usuwając) foldery bin i obj, a następnie wyczyścić pamięć podręczną przeglądarki? Wygląda na to, że robisz wszystko poprawnie (od pierwszego spojrzenia). – Pseudonym

+0

@Pseudonim Całkowicie rozumiem, ale tak, byłem na tej drodze. –

+0

Okay Będę musiał przejrzeć twoje pytanie jeszcze raz – Pseudonym

Odpowiedz

9

Krótka odpowiedź jest taka, że ​​dodajesz MVC wyjątków filtra zamiast Web API Exception Filter.

Twoje czeki wdrożeniowe dla ExceptionContext zamiast HttpActionExecutedContext

public override void OnException(HttpActionExecutedContext actionExecutedContext) 

Ponieważ wola ramy podnosi Http Wyjątek zamiast MVC wyjątek, Twój OnException metoda obejścia nie jest wyzwalany.

Więc bardziej kompletny przykład:

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

Kolejnym ważnym krokiem jest, aby zarejestrować swoją globalną Web API wyjątków filtra w WebApiConfig.cs w sposobie Register(HttpConfiguration config).

public static void Register(HttpConfiguration config) 
{ 

... 

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

} 
+0

Zamierzam nadać tej zmianie strzał. Ale nawet jeśli to naprawi filtr, dlaczego globalna procedura obsługi nie wykryje błędu? –

+1

@MichaelPerrenoud, dodałem do mojej odpowiedzi. Jist jest taki, że ** Kontekst HTTP ** jest inny niż ** kontekst MVC **. Wyjaśnienie, dlaczego jest dość zaangażowany. Najprostszym sposobem wyjaśnienia tego jest to, że ** Web API ** jest znacznie lżejszym środowiskiem niż pełna ** MVC ** Framework –

+0

@DaveAlperovich - Nie jestem pewien, w jaki sposób doszedłeś do tego wniosku.OP nie dał żadnego wskazania, że ​​korzysta z Web API, ani w samym pytaniu, ani w tagach. Tak więc, będąc najwyraźniej zamierzającym go wypróbować, wydaje się, że twoje założenie jest prawidłowe. Jeszcze jeden przypadek, w którym ktoś nieprawidłowo otagował swoje pytanie, ponieważ wydaje się, że nie ma to nic wspólnego z ASP.NET MVC, który jest zupełnie innym środowiskiem niż Web API. Jestem pewien, że odpowiedź byłaby szybsza, gdyby informacje te zostały uwzględnione w pytaniu. – NightOwl888

0

Dave Alperovich odpowiedź będzie rozwiązać problem przy użyciu HttpActionExecutedContext

public override void OnException(HttpActionExecutedContext context) 

Jednak jak próbujesz uchwycić wszystkie możliwe wyjątki aplikacja może generować wtedy oprócz filtrów wyjątków należy stosować ładowarki wiadomość także. Szczegółowe wyjaśnienie można znaleźć tutaj - http://www.asp.net/web-api/overview/error-handling/web-api-global-error-handling.

Podsumowując, istnieje wiele przypadków, w których filtry wyjątków nie mogą obsłużyć. Na przykład:

  • Wyjątki generowane przez konstruktorów sterowników.
  • Wyjątki generowane przez komunikatory.
  • Wyjątki zgłaszane podczas routingu.
  • wyjątki rzucane podczas zawartości odpowiedź serializacji

Więc Jeśli wystąpi błąd nieobsługiwany z dowolnego miejsca w aplikacji, Twój Exception Handler będzie go złapać i pozwala na podjęcie konkretnych działań.

//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 })); 
     } 
    } 
Powiązane problemy