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_Error
Web Forms 및 MVC에서이 작업을 잘 구현 했습니다. Web Api에서 무엇을 사용할 수 있습니까?
답변
이제 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());
답변
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()));
답변
내 질문에 답하기 위해 이것은 불가능합니다!
내부 서버 오류를 일으키는 모든 예외를 처리하는 것은 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
답변
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);
}
}
}
답변
알지 못하는 기존 try-catch 블록이있을 수 있습니다.
내 새 global.asax.Application_Error
메서드가 레거시 코드에서 처리되지 않은 예외에 대해 일관되게 호출되지 않는다고 생각했습니다 .
그런 다음 예외 텍스트에서 Response.Write를 호출 한 호출 스택 중간에서 몇 개의 try-catch 블록을 발견했습니다. 그거였다. 화면에 텍스트를 버리고 예외 돌을 죽였습니다.
그래서 예외가 처리되고 있었지만 처리는 아무런 도움이되지 않았습니다. 일단 try-catch 블록을 제거하면 예상대로 Application_Error 메서드에 전파 된 예외가 발생합니다.