2012-08-08 6 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のカスタマイズを維持したいと思います。

+0

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

答えて

8

代わりのHttpResponseExceptionを投げ、私はちょうど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

属性ベースのアプローチを使用している私は大成功で行っています。 、カスタム属性がある

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

グローバル例外フィルタが動作していないのと同じ問題がありました。解決策は、Web API例外フィルタをASP.NET MVC例外フィルタとは異なるグローバルコレクションに構成する必要があることです。だから、ASPを設定するには、

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

しかし、あなたが実行する必要があり取り扱うウェ​​ブAPIエラーのために:

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

のWeb APIとの私の限られた経験から、この種の状況は、典型的なものである:表面的パターンを使用しますが、実行します取り扱いNET MVCエラーASP.NET MVCと非常によく似ているので、すぐに使い慣れたものになります。これは、1つのコードを書くことが両方のフレームワークに影響を及ぼすという錯覚を与えますが、実際にはそれらの実装は大部分または完全に独立しており、2つのバージョンのコードを書く必要があります作業。

ウェブAPI例外処理に優れ参照:私はGlobalExceptionHandlerを使用してハンドラを委任で例外をキャッチし、カスタムJSONオブジェクトを返すことができることを見出した

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

:startup.csでhttp://www.asp.net/web-api/overview/web-api-routing-and-actions/exception-handling

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 ";   
     } 
    } 
関連する問題