2017-04-05 3 views
0

エラーをキャプチャしてログに記録するフィルタがありますが、クライアントアプリケーションがまともなエラーメッセージを表示できるように、正しいHttpStatusCodeを返すようにします。 現在、フィルタの属性のオーバーライドOnExceptionメソッドでは、例外をキャストしてHttpExceptionとしてステータスコードを取得しようとしています。FilterAttributesを使用したWeb API例外処理

public class LogExceptionFilterAttribute : ExceptionFilterAttribute 
{ 

    // Private properties 
    private readonly ILogProvider _logger; 

    /// <summary> 
    /// Our default constructor 
    /// </summary> 
    /// <param name="logger"></param> 
    public LogExceptionFilterAttribute(ILogProvider logger) 
    { 
     _logger = logger; 
    } 

    /// <summary> 
    /// Invoked when an exception has been thrown 
    /// </summary> 
    /// <param name="context">The context</param> 
    public override async void OnException(HttpActionExecutedContext context) 
    { 

     // Get our user 
     var requestContext = context.Request.GetRequestContext(); 
     var user = requestContext.Principal.Identity; 

     // Create our response 
     var message = await _logger.ErrorAsync(context.Exception, user); 
     var content = new HttpResponseMessage 
     { 
      Content = new StringContent(message), 
      StatusCode = GetStatusCodeFromException(context) 
     }; 

     // Assign our response to our context 
     context.Response = content; 
    } 

    /// <summary> 
    /// Gets a status code from an error 
    /// </summary> 
    /// <param name="context">The context</param> 
    /// <returns></returns> 
    private static HttpStatusCode GetStatusCodeFromException(HttpActionExecutedContext context) 
    { 

     // Cast the exception as an HttpException 
     var exception = context.Exception as HttpException; 

     // If we don't have an exception 
     if (exception != null) 
     { 

      // Return the HttpException code 
      return (HttpStatusCode)exception.GetHttpCode(); 
     } 

     // Return Internal Server Error 
     return HttpStatusCode.InternalServerError; 
    } 
} 

私は、ステータスコードは、常にこの問題を解決するには500

なります返されます、私は追加したいほとんどのエラーがHttpExceptionsとしてキャストすることができないことを実現:これは、このようになります 例外の種類をチェックし、それに応じて処理してください。 私はこれを行うための最善の方法は、このようなswitch文を作成することと判断しました:

private static HttpStatusCode GetStatusCodeFromException(HttpActionExecutedContext context) 
{ 

    // Cast the exception as an HttpException 
    var exception = context.Exception as HttpException; 

    // If there is still an exception, return the code 
    if (exception != null) 
     return (HttpStatusCode)exception.GetHttpCode(); 

    // Otherwise, work out what type of error we have 
    switch(context.Exception.GetType().ToString()) 
    { 
     case "NullReferenceException": 
      return HttpStatusCode.BadRequest; 
     default: 
      return HttpStatusCode.InternalServerError; 
    } 
} 

しかし、今、私はそれが正しいかどうかを確認していません。 誰かがこれを拡張したり、これを行うためのよりよい方法を教えてくれますか?

+0

「NullReferenceException」をキャッチするのが誤植であることを願っています。 –

+1

'NullReferenceException'は悪い要求ではありません。それは完璧な 'InternalServerError'です。 – Evk

+1

httpからの通常のステータスは、200 Doneです。したがって、200の例外を作成する必要はありません。ステータスコードはサーバーによって異なるため、同じエラーで常に500を受け取るとは限りません。サーバーを維持している人は、ハッカーがエラーメッセージをリバースエンジニアリングして真のエラーについて可能な限り情報を提供しないようにします。 – jdweng

答えて

0

代わりにその名前をタイプを比較すると、実際に型自体をチェックするためにはるかに安全です:

if (context.Exception is NullReferenceException) 
{ 
    return HttpStatusCode.BadProgrammer; 
} 
else 
{ 
    return HttpStatusCode.InternalServerError; 
} 
+0

私はswitch文としてそれを行うことはできませんか? if文が大量になるように思えます – r3plica

+0

[C#7の場合はyes](https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp- 7-0 /)。 「パターン付きステートメントを切り替える」を検索します。 –

0

私が正しいよう@Patrickホフマンの答えをマークしているが、私が作るためにC#7を使用switch文は、次のようになります。

private static HttpStatusCode GetStatusCodeFromException(HttpActionExecutedContext context) 
{ 

    // Cast the exception as an HttpException 
    var exception = context.Exception as HttpException; 

    // If there is still an exception, return the code 
    if (exception != null) 
     return (HttpStatusCode)exception.GetHttpCode(); 

    // Witch on the exception type 
    switch (context.Exception) 
    { 
     case ObjectNotFoundException ex: 
      return HttpStatusCode.NotFound; 
     default: 
      return HttpStatusCode.InternalServerError; 
    } 
} 
関連する問題