ASP에서 *all* 예외 처리를 사용하지 않도록 설정합니다.NET Web API 2 (나만의 공간을 만들기 위해)?
미들웨어 구성 요소에서 예외 처리를 배선하고 싶습니다. 다음과 같은 것입니다.
public override async Task Invoke(IOwinContext context)
{
try
{
await Next.Invoke(context);
}
catch (Exception ex)
{
// Log error and return 500 response
}
}
제가 몇 가지 사항은 되어 입니다 입니다.HttpErrorResponse
내가 그들에게 가기 전에 웹 API 파이프라인으로 s.그 과정에서 오류에 대한 세부 정보가 많이 손실되기 때문에 디버깅 등을 할 때 유용한 스택 트레이스를 얻을 수 없습니다(디버거는 예외를 던졌을 때도 멈추지 않습니다 - 수동으로 코드를 뒤져서 어디에서 실패하는지 확인해야 합니다...).
다음과 같은 구현을 통해 사용자 지정 예외 처리기를 추가하려고 했습니다.
public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
var owinContext = context.Request.GetOwinContext();
owinContext.Set(Constants.ContextKeys.Exception, context.Exception);
return Task.FromResult(0);
}
를 통하여 config.Services.Replace(typeof(IExceptionHandler), new MyExceptionHandler());
Next.Invoke(context)
를 통하여
context.Get<Exception>(Constants.ContextKeys.Exception);
여전히 원하는 세부 정보를 제공하지 못할 뿐만 아니라 디버거의 장애 지점에서 멈추지 못합니다.
내장된 모든 오류 처리를 완전히 꺼서 미들웨어가 처리할 수 있는 방법이 있습니까?
해명, 많은 사람들이 내가 무엇을 추구하는지 오해하는 것 같기 때문입니다.
- 웹 API의 기본 제공 오류 처리는 일부(모두는 아니지만) 예외를 잡아 500개의 응답으로 다시 씁니다.
- 모든 예외를 잡고 로깅을 수행한 다음 선택한 정보로 500개의 응답을 내보내고 싶습니다(대부분은 다음 글머리표 참조)
- 비즈니스 로직 오류를 나타내는 몇 가지 예외 사항도 있습니다. 대신 오류 40배를 반환하고자 합니다.
- 이것이 (앱) 파이프라인의 맨 위에 있기를 바랍니다. 즉, 요청 라이프사이클의 다른 모든 것을 포장하는 것입니다.
- 이 문제를 OWIN을 사용하여 처리하여 향후 가능한 자체 호스팅 시나리오로 이동할 수 있도록 하고 싶습니다(즉, 이 앱이 IIS에서 항상 호스팅된다는 것이 전혀 명시되어 있지 않습니다. Global.asax.cs 등은 여기와 관련이 없습니다).
업데이트: 블로그에 올린 내용입니다.블로그 게시물을 조사해보니 개선 가능성이 발견되었고, 이 답변의 관련 부분을 업데이트했습니다.여기 있는 다른 모든 제안이나 기본 동작보다 이것이 더 낫다고 생각하는 이유에 대한 자세한 내용은 게시물 전체를 읽어보세요 :)
저는 이제 다음과 같은 접근 방식을 취했는데, 이 접근 방식은 제가 찾던 것과 100% 일치하지 않더라도 잘 작동하는 것 같습니다.
클래스생성
PassthroughExceptionHandler
:public class PassthroughExceptionHandler : IExceptionHandler { public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken) { // don't just throw the exception; that will ruin the stack trace var info = ExceptionDispatchInfo.Capture(context.Exception); info.Throw(); return Task.CompletedTask; } }
그 수업이 그 수업을 대체하게 해주세요.
IExceptionHandler
웹 API 서비스:config.Services.Replace(typeof(IExceptionHandler), new PassthroughExceptionHandler());
내가 원하는 작업을 수행하는 미들웨어 클래스를 만듭니다.
public class ExceptionHandlerMiddleware { public override async Task Invoke(IOwinContext context) { try { await Next?.Invoke(context); } catch (Exception ex) { // handle and/or log } } }
미들웨어를 스택에 먼저 등록합니다.
app.Use<ExceptionHandlerMiddleware>() .UseStageMarker(PipelineStage.Authenticate) // other middlewares omitted for brevity .UseStageMarker(PipelineStage.PreHandlerExecute) .UseWebApi(config);
나는 여전히 누구에게나 현상금을 수여할 것입니다. (혜택이 만료됨...) 더 나은 해결책을 찾고 있습니다. 예를 들어, 처리되지 않은 예외를 처리할 때 깨지는 것입니다. (이 방법은 처리기에서 예외를 다시 처리할 때 VS가 깨집니다.그러나 원래 콜 스택이 손실됩니다. 오류가 발생한 회선에 중단점을 설정하고 예외가 발생했을 때 상태를 가로챌 수 있도록 다시 디버그해야 합니다.)
이것이 당신에게 도움이 될지는 모르겠지만, 나는 오류가 발견되지 않았더라도 모든 오류를 JSON으로 다시 보내야 하는 비슷한 요구사항이 있습니다.기본 컨트롤러를 만들고 ExecuteAsync를 덮어쓰면 응답을 만들 수 있습니다.
public class ControllerBase : ApiController
{
protected string ClassName = "ControllerBase::";
public override System.Threading.Tasks.Task<HttpResponseMessage> ExecuteAsync(System.Web.Http.Controllers.HttpControllerContext controllerContext, System.Threading.CancellationToken cancellationToken)
{
try
{
System.Threading.Tasks.Task<HttpResponseMessage> TaskList = base.ExecuteAsync(controllerContext, cancellationToken);
if (TaskList.Exception != null && TaskList.Exception.GetBaseException() != null)
{
JSONErrorResponse AsyncError = new JSONErrorResponse();
AsyncError.ExceptionMessage = TaskList.Exception.GetBaseException().Message;
AsyncError.ErrorMessage = string.Format("Unknown error {0} ExecuteAsync {1}", ClassName ,controllerContext.Request.RequestUri.AbsolutePath);
AsyncError.HttpErrorCode = HttpStatusCode.BadRequest;
HttpResponseMessage ErrorResponse = controllerContext.Request.CreateResponse(AsyncError.HttpErrorCode, AsyncError);
return System.Threading.Tasks.Task.Run<HttpResponseMessage>(() => ErrorResponse);
}
return TaskList;
}
catch (Exception Error)
{
JSONErrorResponse BadParameters = new JSONErrorResponse();
BadParameters.ExceptionMessage = Error.Message;
BadParameters.ErrorMessage = string.Format("Method [{0}], or URL [{1}] not found, verify your request", controllerContext.Request.Method.Method, controllerContext.Request.RequestUri.AbsolutePath);
BadParameters.HttpErrorCode = HttpStatusCode.NotFound;
HttpResponseMessage ErrorResponse = controllerContext.Request.CreateResponse(BadParameters.HttpErrorCode, BadParameters);
return System.Threading.Tasks.Task.Run<HttpResponseMessage>(() => ErrorResponse);
}
}
}
public class JSONErrorResponse
{
//Possible message from exception
public string ExceptionMessage { get; set; }
//Possible custom error message
public string ErrorMessage { get; set; }
//Http error code
public HttpStatusCode HttpErrorCode { get; set; }
}
또한 컨트롤러 활성화기를 직접 만들고 사용자 지정 예외 처리기를 가지고 ExceptionFilterAttribute를 사용해 볼 수도 있습니다.
컨트롤러 액티베이터 만들기
public class ExceptionHandlingControllerActivator : IHttpControllerActivator { private readonly IHttpControllerActivator _concreteActivator; public ExceptionHandlingControllerActivator(IHttpControllerActivator concreteActivator) { _concreteActivator = concreteActivator; } public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) { try { return _concreteActivator.Create(request, controllerDescriptor, controllerType); } catch (Exception ex) { // do stuff with the exception throw new HttpResponseException(request.CreateResponse(HttpStatusCode.InternalServerError, new ResponseModel(ex))); } } }
ExceptionFilter 특성 만들기
public class ExceptionHandlingFilter : ExceptionFilterAttribute { public override void OnException(HttpActionExecutedContext context) { // do stuff with the exception var request = context.Request; ResponseModel respMod = null; // Example: if debug constant is not defined, mask exception, otherwise create normal object with message, inner exception and stacktrace #if !DEBUG respMod = new ResponseModel(context.Exception, context.Exception.Message, true); #else respMod = new ResponseModel(context.Exception); #endif context.Response = request.CreateResponse(HttpStatusCode.InternalServerError, respMod); } }
ResponseModel은 Formaters를 사용하여 JSON에 직렬화하고 모든 컨트롤러 응답에 의해 반환되는 클래스이므로 클라이언트는 HTTP 상태 코드 외에도 성공적인 응답뿐만 아니라 오류 데이터를 식별할 수 있습니다.
config.Formatters.Clear(); // do not need any other config.Formatters.Add(new JsonMediaTypeFormatter());
와이어업
// ... [cut] ... config.Filters.Add(new ExceptionHandlingFilter()); // ... [cut] ... config.Services.Replace(typeof(IHttpControllerActivator), new ExceptionHandlingControllerActivator(config.Services.GetHttpControllerActivator()) ); // ... [cut] ... app.UseWebApi(config);
OWIN은 웹 api 자체 오류 처리 기능이 내장되어 있기 때문에 그런 예외를 처리하지 않는 것으로 되어 있습니다.OWIN은 애플리케이션과 분리되도록 설계되었습니다.예외 처리기의 HandleAsync 메서드에 중단점을 설정한 경우 컨텍스트 변수를 검사하고 예외의 세부 정보를 볼 수 있어야 합니다.
디버깅 목적으로만 이 작업을 수행하려는 경우 중단점을 설정하면 예외를 볼 수 있습니다.예외 사항을 기록해야 한다면 예외 처리자가 가장 적합하다고 생각합니다.
도움이 되길 바랍니다.
다음과 같은 도움이 될 수 있습니다.
https://stackoverflow.com/a/21382651/1419853
http://www.asp.net/web-api/overview/releases/whats-new-in-aspnet-web-api-21#global-error
기본적으로 오류를 파악, 처리 및 변경하기 위한 지원 기능이 내장되어 있습니다.
다음과 같습니다.
public class ExceptionLogger : System.Web.Http.ExceptionHandling.ExceptionLogger
{
Logger _logger;
public ExceptionLogger(Logger logger)
{
_logger = logger;
}
public override void Log(ExceptionLoggerContext context)
{
_logger.Error(context.ExceptionContext.Exception.ToString());
}
}
언급URL : https://stackoverflow.com/questions/34201527/disable-all-exception-handling-in-asp-net-web-api-2-to-make-room-for-my-own
'programing' 카테고리의 다른 글
iPhone vs iPad/Browser HTML5 인라인 비디오 (0) | 2023.09.19 |
---|---|
element.remove를 호출할 때 $destroy가 트리거되지 않는 이유는 무엇입니까? (0) | 2023.09.19 |
프로토콜 기능이 Self를 반환합니다. (0) | 2023.09.14 |
MySQL의 계층 데이터에서 깊이 기반 트리 생성(CTE 없음) (0) | 2023.09.14 |
도커 스웜은 볼륨 공유를 어떻게 구현합니까? (0) | 2023.09.14 |