2012-08-08 2 views
13

WebApi 메시지 핸들러에서 예외를 반환하는 방법 \ WebApi 응용 프로그램 등록정상적으로 내 MVC에서 글로벌 ExceptionFilter이

public class MyExceptionFilter : ExceptionFilterAttribute 
{ 
    private readonly IMyExceptionHandler m_exceptionHandler; 

    public MyExceptionFilter(IMyExceptionHandler exceptionHandler) 
    { 
     m_exceptionHandler = exceptionHandler; 
    } 

    public override void OnException(HttpActionExecutedContext context) 
    { 
     Exception ex = context.Exception; 
     if (ex != null) 
     { 
      object response = null; 
      HttpStatusCode statusCode = m_exceptionHandler != null 
       ? m_exceptionHandler.HandleException(ex, out response) 
       : HttpStatusCode.InternalServerError; 
      context.Response = context.Request.CreateResponse(statusCode, response ?? ex); 
     } 

     base.OnException(context); 
    } 
} 

이 필터는 모든 예외를 반환 json-objects로 사용하고 일부 IMyExceptionHandler-implementation은 반환되는 객체를 사용자 정의 할 수 있습니다.

이 모든 것이 잘 작동합니다. 내 메시지 핸들러에서 예외를 설정해야까지 :

이 핸들러를 볼 수 있듯이
public class FooMessageHandler : DelegatingHandler 
{ 
    private readonly Func<IBar> _barFactory; 
    public FooMessageHandler(Func<IBar> barFactory) 
    { 
     _barFactory = varFactory; 
    } 

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     request.Properties["MY_BAR"] = _barFactory(); 
     return base.SendAsync(request, cancellationToken); 
    } 
} 

몇 가지 구성 요소를 만들고 현재 HTTP 요청 메시지에 넣어. FuncOfIBar에서 예외가 발생하면 죽음의 황색 화면이 나타납니다. 내 ExceptionFilter가 호출되지 않습니다.

은 내가 특별히 메시지 처리기에서 예외를 잡아 HttpResponseException를 반환하는 시도했지만 아무것도 변경되지 않습니다 - 여전히 점점 YSOD :

public class XApplicationInitializerMessageHandler : DelegatingHandler 
{ 
    private readonly Func<IXCoreApplication> _appFactory; 
    private readonly IXExceptionHandler m_exceptionHandler; 

    public XApplicationInitializerMessageHandler(Func<IXCoreApplication> appFactory, IXExceptionHandler exceptionHandler) 
    { 
     ArgumentValidator.EnsureArgumentNotNull(appFactory, "appFactory"); 
     _appFactory = appFactory; 
     m_exceptionHandler = exceptionHandler; 
    } 

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     try 
     { 
      request.SetApplication(_appFactory()); 
     } 
     catch (Exception ex) 
     { 
      object resultObject = null; 
      HttpStatusCode statusCode = m_exceptionHandler != null 
       ? m_exceptionHandler.HandleException(ex, out resultObject) 
       : HttpStatusCode.InternalServerError; 
      HttpResponseMessage responseMessage = request.CreateResponse(statusCode, resultObject ?? ex); 

      throw new HttpResponseException(responseMessage); 
     } 
     return base.SendAsync(request, cancellationToken); 
    } 
} 

}

내가 할 내 응용 프로그램의 동작을 원하지을 ApiController 또는 메시지 핸들러에서 예외가 발생하는 위치와 관계없이 동일합니다.

어떻게 수행하나요?

나는 Application_Error에 대해 알고 있지만 HttpApplication 사용자 지정을 건드리지 않고 유지하려고합니다. 대신 난 그냥 반환해야 HttpResponseException을 던지는

+0

http://stackoverflow.com/questions/13013973/asp-net-web-api-default-error-messages – Timeless

답변

8

HttpResponseMessage :

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
{ 
    try 
    { 
     request.SetApplication(_appFactory()); 
    } 
    catch (Exception ex) 
    { 
     object resultObject = null; 
     HttpStatusCode statusCode = m_exceptionHandler != null 
      ? m_exceptionHandler.HandleException(ex, out resultObject) 
      : HttpStatusCode.InternalServerError; 
     HttpResponseMessage responseMessage = request.CreateResponse(statusCode, resultObject ?? ex); 

     return Task<HttpResponseMessage>.Factory.StartNew(() => responseMessage); 
    } 
    return base.SendAsync(request, cancellationToken); 
} 
5

내가 속성 기반의 접근 방식을 사용하고 succes에 함께 할 것을. 사용자 정의 속성은

public class ExceptionHandlingAttribute : ExceptionFilterAttribute 
{ 
    public override void OnException(HttpActionExecutedContext context) 
    {} 

당신을 볼 수 있듯이 :

[ExceptionHandling] 
public IEnumerable<string> Get() 

귀하의 사용자 정의 예외 처리 속성은 다음과 같이 구현됩니다 : 당신은 예외 처리를 사용해야 할 조치의 각 상에 사용자 지정 특성을 배치 ExceptionFilterAttribute에서 상속됩니다. 그런 다음 OnException 메서드를 재정의합니다. 그렇다면 예외 유형을 살펴보고 비즈니스 규칙 또는 필요에 따라 처리하십시오. 어떤 경우에는 서버에서 예외를 삼킬 수도 있습니다. 클라이언트에 알리고 싶으면 HttpResponseException을 던져서 메시지, 호출 스택, 내부 예외 등과 같은 모든 관련 정보를 보유 할 수 있습니다.

자세한 내용은 ASP.NET Web API Exception Handling을 참조하십시오.

5

전역 예외 필터가 실행되지 않는 것과 동일한 문제가있었습니다. 해결책은 웹 API 예외 필터를 ASP.NET MVC 예외 필터가 아닌 다른 전역 컬렉션에 구성해야한다는 것입니다.

그래서 ASP를 구성하십시오.처리 NET MVC 오류 당신은 실행됩니다 :

System.Web.Mvc.GlobalFilters.Filters.Add(new MyMvcExceptionFilter()); 

그러나 웹 API 오류에 대한

는 실행해야합니다 처리 :

System.Web.Http.GlobalConfiguration.Configuration.Filters.Add(new MyWebApiExceptionFilter()); 

를 웹 API 내 제한된 경험에서 이러한 유형의 상황은 전형적인 : 표면적으로 패턴 사용 ASP.NET MVC와 매우 유사하므로 즉시 익숙합니다. 이것은 하나의 코드를 작성하는 것이 두 프레임웍 모두에 영향을 미칠 것이라는 착각을 불러 일으키지 만, 실제로 그것들 아래의 구현은 모두 완전히 또는 완전히 분리되어 있으므로 모두 비슷하게 만드는 두 가지 버전의 코드를 작성해야합니다 작업. 웹 API 예외 처리에

우수한 참조 : http://www.asp.net/web-api/overview/web-api-routing-and-actions/exception-handling

2

startup.cs에서는 :

config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler()); 

나는 발견 GlobalExceptionHandler이 핸들러를 위임에 예외를 catch 및 사용자 정의 JSON 객체를 반환 할 수 있습니다 사용.

0

나는 아주 좋은 예와 함께이 블로그를 발견 : 나는 일부 업데이트와 코드를 채택 http://nodogmablog.bryanhogan.net/2016/07/getting-web-api-exception-details-from-a-httpresponsemessage/

: 사용

if ((int)response.StatusCode >= 400) 
{ 
     exceptionResponse = JsonConvert.DeserializeObject<ExceptionResponse>(LogRequisicao.CorpoResposta); 
     LogRequisicao.CorpoResposta = exceptionResponse.ToString() ; 
     if (exceptionResponse.InnerException != null) 
      LogRequisicao.CorpoResposta += "\r\n InnerException: " + exceptionResponse.ToString(); 
} 

을 객체 :

public class ExceptionResponse 
    { 
     public string Message { get; set; } 
     public string ExceptionMessage { get; set; } 
     public string ExceptionType { get; set; } 
     public string StackTrace { get; set; } 
     public ExceptionResponse InnerException { get; set; } 

     public override String ToString() 
     { 
      return "Message: " + Message + "\r\n " 
       + "ExceptionMessage: " + ExceptionMessage + "\r\n " 
       + "ExceptionType: " + ExceptionType + " \r\n " 
       + "StackTrace: " + StackTrace + " \r\n ";   
     } 
    } 
관련 문제