ASP.NET Web Api에서 처리되지 않은 모든 예외 포착


113

ASP.NET Web Api에서 발생하는 처리되지 않은 모든 예외를 어떻게 포착 하여 기록 할 수 있습니까?

지금까지 시도했습니다.

  • 생성 및 등록 ExceptionHandlingAttribute
  • Application_Error메서드 구현Global.asax.cs
  • 구독 AppDomain.CurrentDomain.UnhandledException
  • 구독 TaskScheduler.UnobservedTaskException

ExceptionHandlingAttribute컨트롤러 작업 메서드 및 작업 필터 내에서 throw 된 예외를 성공적으로 처리하지만 다른 예외는 처리되지 않습니다. 예를 들면 다음과 같습니다.

  • IQueryable작업 메서드 에서 반환 된 실행에 실패 할 때 throw되는 예외
  • 메시지 처리기에 의해 throw 예외 (예 HttpConfiguration.MessageHandlers)
  • 컨트롤러 인스턴스를 만들 때 throw되는 예외

기본적으로 예외로 인해 500 내부 서버 오류가 클라이언트에 반환되는 경우 로깅을 원합니다. Application_ErrorWeb Forms 및 MVC에서이 작업을 잘 구현 했습니다. Web Api에서 무엇을 사용할 수 있습니까?


ASP.NET 상태 모니터링을 사용해 보셨습니까 ? 활성화하고 예외가 이벤트 로그에 기록되지 않는지 확인하십시오.
John Saunders

상태 모니터링은 내 MVC 파이프 라인 예외를 포착하지만 Web Api 파이프 라인 예외는 포착하지 않습니다.
Joe Daley

감사합니다-생성자 / 종속성 주입 문제를 로깅 할 수없는 이유를 파악하는 데 시간이 좀 걸렸습니다. WebAPI 로깅이 이미 정렬되어 있다고 생각했습니다 ...
Overflew

답변:


156

이제 WebAPI 2.1에서 가능합니다 ( 새로운 기능 참조 ).

IExceptionLogger 구현을 하나 이상 만듭니다. 예를 들면 :

public class TraceExceptionLogger : ExceptionLogger
{
    public override void Log(ExceptionLoggerContext context)
    {
        Trace.TraceError(context.ExceptionContext.Exception.ToString());
    }
}

그런 다음 다음과 같이 구성 콜백 내에서 애플리케이션의 HttpConfiguration에 등록합니다.

config.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());

또는 직접 :

GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());

7
@NeilBarnwell 예, Web API 2.1은 System.Web.Http 어셈블리 버전 5.1.0에 해당합니다 . 따라서 여기에 설명 된 솔루션을 사용하려면이 버전 이상이 필요합니다. 참조 nuget 패키지 버전
decates

2
예를 들어 특정 500 개의 오류는 여전히 이것에 의해 잡히지 않습니다. HttpException-원격 호스트가 연결을 닫았습니다. global.asax Application_Error가 웹 API 처리 외부의 오류를 처리 할 수있는 장소가 아직 있습니까?
Avner 2015-06-03

11
나는 공식 doco가 msdn에 얼마나 자세하고 개발자의 99 %가 정말로 원하는 것은 오류를 기록하는 코드 8 줄뿐입니다.
Rocklan

20

Yuval의 대답은 링크 된 페이지 에 명시된대로 로깅이 아닌 Web API에서 포착 된 처리되지 않은 예외에 대한 응답을 사용자 지정하는 것 입니다. 자세한 내용은 페이지의 사용시기 섹션을 참조하십시오. 로거는 항상 호출되지만 핸들러는 응답을 보낼 수있는 경우에만 호출됩니다. 간단히 말해서 로거 를 사용하여 로그하고 핸들러를 사용하여 응답을 사용자 정의하십시오.

그건 그렇고, 나는 어셈블리 v5.2.3을 사용하고 있으며 ExceptionHandler클래스에는 HandleCore메서드 가 없습니다 . 이에 상응하는 것은 Handle. 그러나 단순히 하위 클래스 지정 ExceptionHandler(Yuval의 답변에서와 같이)은 작동하지 않습니다. 제 경우에는 IExceptionHandler다음과 같이 구현 해야합니다.

internal class OopsExceptionHandler : IExceptionHandler
{
    private readonly IExceptionHandler _innerHandler;

    public OopsExceptionHandler (IExceptionHandler innerHandler)
    {
        if (innerHandler == null)
            throw new ArgumentNullException(nameof(innerHandler));

        _innerHandler = innerHandler;
    }

    public IExceptionHandler InnerHandler
    {
        get { return _innerHandler; }
    }

    public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
    {
        Handle(context);

        return Task.FromResult<object>(null);
    }

    public void Handle(ExceptionHandlerContext context)
    {
        // Create your own custom result here...
        // In dev, you might want to null out the result
        // to display the YSOD.
        // context.Result = null;
        context.Result = new InternalServerErrorResult(context.Request);
    }
}

로거와 달리 추가가 아닌 기본 핸들러를 대체하여 핸들러를 등록합니다.

config.Services.Replace(typeof(IExceptionHandler),
    new OopsExceptionHandler(config.Services.GetExceptionHandler()));

1
이것은 훌륭한 솔루션이며 '모든 오류를 포착하거나 기록'하는 데 허용되는 솔루션이어야합니다. ExceptionHandler를 확장 할 때 왜 작동하지 않았는지 알 수 없었습니다.
Rajiv

훌륭한 솔루션입니다. 요청에 대해 MVC 파이프 라인이로드되면 이것은 잘 작동합니다. IIS는 startup.cs에서 OWIN을 회전시킬 때를 포함하여 그때까지 예외를 처리합니다. 그러나 스핀 업이 startup.cs 처리를 마친 후 어느 시점에서 훌륭하게 작동합니다.
Gustyn

18

내 질문에 답하기 위해 이것은 불가능합니다!

내부 서버 오류를 일으키는 모든 예외를 처리하는 것은 Web API가 가져야하는 기본 기능처럼 보이므로 Microsoft 에 Web API에 대한 글로벌 오류 처리기를 요청했습니다 .

https://aspnetwebstack.codeplex.com/workitem/1001

동의하면 해당 링크로 이동하여 투표하십시오!

한편, 훌륭한 기사 인 ASP.NET Web API Exception Handling 은 몇 가지 다른 범주의 오류를 포착하는 몇 가지 방법을 보여줍니다. 해야 할 것보다 더 복잡하고 모든 것을 잡을 수는 없습니다. 내부 서버 오류를 못하지만 오늘날 사용할 수있는 최선의 접근 방식입니다.

업데이트 : 이제 전역 오류 처리가 구현되어 야간 빌드에서 사용할 수 있습니다! ASP.NET MVC v5.1에서 출시 될 예정입니다. 작동 방식은 다음과 같습니다. https://aspnetwebstack.codeplex.com/wikipage?title=Global%20Error%20Handling


대신 웹 API의 아약스 통화 사용 컨트롤러 이유처럼 보인다 .. 경계입니다 이미 ELMAH 그것을 캡처 할 수 있다면, 어쩌면 방법이 있지만 .. 흐릿한
소닉 소울

4
이제 전역 오류 처리가 Web API 2.1에 추가되었습니다. 자세한 내용은 내 대답을 참조하십시오.
decates

10

IExceptionHandler인터페이스 를 구현 하거나 ExceptionHandler기본 클래스를 상속하여 전역 예외 처리기를 만들 수도 있습니다 . 모든 등록 후 실행 체인에서 마지막으로 호출됩니다 IExceptionLogger.

IExceptionHandler는 모든 컨트롤러에서 처리되지 않은 모든 예외를 처리합니다. 이것은 목록의 마지막입니다. 예외가 발생하면 IExceptionLogger가 먼저 호출되고 컨트롤러 ExceptionFilter가 호출되고 여전히 처리되지 않은 경우 IExceptionHandler 구현이 호출됩니다.

public class OopsExceptionHandler : ExceptionHandler
{
    public override void HandleCore(ExceptionHandlerContext context)
    {
        context.Result = new TextPlainErrorResult
        {
            Request = context.ExceptionContext.Request,
            Content = "Oops! Sorry! Something went wrong."        
        };
    }

    private class TextPlainErrorResult : IHttpActionResult
    {
        public HttpRequestMessage Request { get; set; }

        public string Content { get; set; }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            HttpResponseMessage response = 
                             new HttpResponseMessage(HttpStatusCode.InternalServerError);
            response.Content = new StringContent(Content);
            response.RequestMessage = Request;
            return Task.FromResult(response);
        }
    }
}

여기 에 더 많은 것들이 있습니다 .


궁금한 점은 어디에 등록되어 있습니까?
ThunD3eR

-1

알지 못하는 기존 try-catch 블록이있을 수 있습니다.

내 새 global.asax.Application_Error메서드가 레거시 코드에서 처리되지 않은 예외에 대해 일관되게 호출되지 않는다고 생각했습니다 .

그런 다음 예외 텍스트에서 Response.Write를 호출 한 호출 스택 중간에서 몇 개의 try-catch 블록을 발견했습니다. 그거였다. 화면에 텍스트를 버리고 예외 돌을 죽였습니다.

그래서 예외가 처리되고 있었지만 처리는 아무런 도움이되지 않았습니다. 일단 try-catch 블록을 제거하면 예상대로 Application_Error 메서드에 전파 된 예외가 발생합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.