10

特定の状況でSerializationExceptionをスローするASP.NET Web API Webサービスがあります。問題は、サーバー側でこの例外をトラップしてログに記録できないことです。クライアント側のHTTP応答の本体に表示される唯一の場所です。Web APIでSerializationExceptionをトラップするにはどうすればよいですか?

私はに記載されているようにExceptionFilterAttributeを登録し、コントローラ内で例外をスローすると正常に動作することを確認しました。残念ながら、SerializationExceptionは応答中(コントローラの後)にスローされ、ASP.NETによって完全に呑み込まれているようです。私もGlobal.asax.csにApplication_Error()をフックしようとしましたが、そこにも表示されませんでした。

Web APIの応答中にSerializationException例外をキャッチするにはどうすればよいですか?

答えて

8

代わりにオブジェクトを返すので、あなたはApiController.CreateResponse()メソッドを使用していて、その後、response.Content.LoadIntoBufferAsync().Wait()を行うことができますし、アクションに残っているため、例外をキャッチすることができながら、それが起こることをシリアル化を強制しますHttpResponseMessageを返し、場合。

+1

完璧!わずかな最適化で、スレッドをブロックしないように、私は非同期で待っていたLoadIntoBufferAsyncを作った。 – Mike

+0

@Mikeおそらく、IOを実行していない可能性があるため、LoadIntoBufferAsyncは、シリアル化プロセス中にメモリ内のバイトを移動するだけです。したがって、非同期にすることで、あるスレッドプールスレッドから別のスレッドプールスレッドに切り替えるだけです。これは実際にperfに悪影響を与えます。しかし、あなたのフォーマッタがIOを待ってブロックされることを知っていれば、asyncが役に立ちます。 –

+1

私は間違いなくWait vs awaitの専門家ではありませんが、私の理解は、タスクが別のスレッドで実行されている間、Wait()が現在のスレッドをブロックすることです。また、現在のスレッドをブロックしますが、非同期にスレッドを解放して他の作業を行い、タスクが完了した時点で再開します。両方のケースでスレッドスイッチが必要なので、パフォーマンスは似ていますが、非同期のアプローチでは(わずかに)よりスケーラビリティが向上します。私が言ったように、これに関する私の知識は不十分ですので、おそらくスティーブン・トゥーブに尋ねるべきです。 :) – Mike

1

ところで、レスポンスがアクションから返された直後ではなく、スタックの下にあるホストレイヤ(IISでホストされているHttpControllerHandlerとSelfHostでホストされているHttpSelfhostServer)では、応答のシリアル化が実際に行われます。

WebAPIのスタックのポスター:http://www.asp.net/posters/web-api/ASP.NET-Web-API-Poster-grayscale.pdf

私はこれを達成するためにまっすぐ進む方法を考え出すことができませんよ、と述べました。これは面倒ですが、デフォルトのXmlとJsonフォーマッタのWriteToStreamAsyncメソッドをオーバーライドして、例外をtry-catch-logするかもしれませんか?

また、シリアル化中に発生した例外を記録するWeb APIトレースを有効にすることもできます。しかし、ええ、逐次化エラーの原因となるリクエストがわからない場合は、常にトレースを有効にして、実行したいことがわからないことがあります。

2

IExceptionHandlerの実装を登録すると、すべてのWeb API例外をキャッチできます。

Web API Global Error Handling

を参照してください。例外フィルタが処理できないという例がいくつかあります。例:

  • コントローラのコンストラクタからスローされた例外。
  • メッセージハンドラからスローされた例外。
  • ルーティング中に例外がスローされました。
  • 応答コンテンツのシリアル化中に例外がスローされました。その記事に記載されていない

ことの一つは、例外フィルタが処理できない場合の数がある経由でIExceptionHandlerが登録されなければならないということです。たとえば:その記事に記載されていない

Exceptions thrown from controller constructors. 
Exceptions thrown from message handlers. 
Exceptions thrown during routing. 
Exceptions thrown during response content serialization . 

一つのことは、あなたのIExceptionHandlerGlobalConfiguration.Configuration.Services.Add(...)またはDependencyResolverで使用されるように構成されたIoCコンテナのいずれかを介して、登録されなければならないということです。

関連する問題