124

ASP.NET Web Api で発生する未処理の例外をすべてキャッチしてログに記録するにはどうすればよいですか?

これまでのところ、私は試しました:

  • を作成して登録するExceptionHandlingAttribute
  • Application_Errorメソッドを実装するGlobal.asax.cs
  • 申し込むAppDomain.CurrentDomain.UnhandledException
  • 申し込むTaskScheduler.UnobservedTaskException

ExceptionHandlingAttribute、コントローラー アクション メソッドおよびアクション フィルター内でスローされた例外を正常に処理しますが、その他の例外は処理されません。次に例を示します。

  • IQueryableアクション メソッドによって返された が実行に失敗したときにスローされる例外
  • メッセージ ハンドラーによってスローされた例外 (つまりHttpConfiguration.MessageHandlers)
  • コントローラー インスタンスの作成時にスローされる例外

基本的に、例外によって 500 Internal Server Error がクライアントに返される場合は、ログに記録する必要があります。実装Application_Errorすると、Web フォームと MVC でこの仕事がうまくいきました - Web Api で何を使用できますか?

4

5 に答える 5

163

これは WebAPI 2.1 で可能になりました ( What's Newを参照):

IExceptionLogger の 1 つ以上の実装を作成します。例えば:

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());
于 2014-01-27T13:53:37.280 に答える
21

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()));
于 2016-03-23T05:20:30.577 に答える
21

私自身の質問に答えるために、これは不可能です!

内部サーバー エラーを引き起こすすべての例外を処理することは、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

于 2013-04-22T23:59:38.630 に答える
-1

認識していない既存の try-catch ブロックがある場合があります。

global.asax.Application_Errorレガシ コードの未処理の例外に対して、新しいメソッドが一貫して呼び出されていないと思いました。

次に、例外テキストで Response.Write を呼び出すコール スタックの途中にいくつかの try-catch ブロックを見つけました。それだけでした。画面にテキストをダンプし、例外の石を殺しました。

そのため、例外は処理されていましたが、処理は何も役に立ちませんでした。これらの try-catch ブロックを削除すると、例外は予想どおり Application_Error メソッドに伝播されました。

于 2017-10-10T13:40:24.757 に答える