2010-12-16 11 views
8

WCF RESTサービスのバックエンドになっているレガシーコードがたくさんあります。以前は通常のWCFサービスバックエンドでした。どのメソッドでも例外を捕捉して分析する仕組みを実装したいと思います。それが既知のエラーであることが判明した場合、処理され、フレンドリーな欠陥に変わります。WCF RESTサービス - 一般的な例外処理

「通常の」例外の代わりにFaultExceptionまたはWebProtocolExceptionをスローすることができますが、例外がコード全体にスローされる場所がたくさんあり、それらのすべてを探すのはかなり苦しい選択です。

標準のWebHttpBehavior.AddServerErrorHandlersメソッドをオーバーライドし、エラーハンドラ(IErrorHandler実装)をエンドポイントディスパッチャエラーハンドラコレクションに追加する新しい動作を作成するエンドポイント動作拡張を追加しようとしました。エラーハンドラの中で私は例外を分析し、この例外に基づいて所望の障害を作成する(または作成しない)。

私は、このメカニズムが既知の例外のカスタムデータを返すと期待していましたが、間違っていました。良い古いMicrosoftは、不可避的に内部Microsoft.ServiceModel.Web.WebErrorHandlerをエンドポイントディスパッチャーエラーハンドラーコレクションの最後に追加する素晴らしい不可避のWebHttpBehavior2を実装しました。このハンドラは、以前に実行されたすべてのハンドラを無視し、少数の例外セットのみを認識しますが、大半は「内部サーバエラー」などと解釈されます。

質問は、私が正しいパスにいるかどうか、WCF RESTメカニズムでこのハンドラを無効にする方法、または新しい例外を導入する方法があります(例外が検出された場合などは、 FaultExceptionなどのスロー/リターンの場合、この新しい例外は元のものではなくMicrosoft.ServiceModel.Web.WebErrorHandlerに提供されます)。 IErrorHandlerと動作拡張を使った私のすべての実験が役に立たない場合、代わりは何ですか?ここでも、私は実際に例外を投げるロジックを変更したくないので、例外をキャッチして処理する必要があります。

ありがとうございます!

答えて

7

WCF SOAPサービスをRESTに変更すると、エラーの報告と処理の考え方全体が変更されます。

SOAPでは、フォルトは契約の一部です。 RESTでは、HTTP応答コードと説明で出力するコードになります。ここで

はキャッチ・スニペットです:

catch (Exception e) 
{ 
    Trace.WriteLine(e.ToString()); 

    OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse; 
    response.StatusCode = System.Net.HttpStatusCode.UnsupportedMediaType; // or anything you want 
    response.StatusDescription = e.Message; 
    return null; // I was returning a class 
} 

だから私はあなたがあなたのために、関連するエラー・コードを作成し、応答に入れヘルパーコードを作成することをお勧め。私はMyErrorHandler過去

public class MyServerBehavior : IServiceBehavior { 

     public void AddBindingParameters(ServiceDescription serviceDescription, 
      ServiceHostBase serviceHostBase, 
      Collection<ServiceEndpoint> endpoints, 
      BindingParameterCollection bindingParameters) { 

     } 

     public void ApplyDispatchBehavior(ServiceDescription serviceDescription, 
              ServiceHostBase serviceHostBase) { 

      foreach (ChannelDispatcher chDisp in serviceHostBase.ChannelDispatchers) { 
       chDisp.IncludeExceptionDetailInFaults = true; 
       if (chDisp.ErrorHandlers.Count > 0) { 
        // Remove the System.ServiceModel.Web errorHandler 
        chDisp.ErrorHandlers.Remove(chDisp.ErrorHandlers[0]); 
       } 
       // Add new custom error handler 
       chDisp.ErrorHandlers.Add(new MyErrorHandler()); 

      } 

     } 

     public void Validate(ServiceDescription serviceDescription, 
          ServiceHostBase serviceHostBase) { 
     } 

    } 

に何をしたか

+0

このようなキャッチは、すべてのサービスメソッドに追加する必要があります。あるいは、すべての例外を処理するために一度だけどこかに書き込む方法はありますか?私はすべての例外に対して共通のハンドラを定義したので、ビヘイビアベースのアプローチが好きでした。それぞれのメソッドごとに例外を処理したり処理したりすることを心配する必要はありませんでした。最も良いことは、エンドポイント内のすべてのサービスに対して1つのプロセッサーを定義したことです。あなたのアプローチを使ってこれを達成することはできません。 –

+0

'StatusDescription'を設定しても効果はありません!レスポンスには常に一般的なステータスの説明があります。とにかくそれを修正するには? – Hemant

+0

です。あなたはfiddlerを使用してサーバーからの送信メッセージでそれを確認できます....しかし、あなたが見つけやすい傾向があるのは、さまざまなブラウザや異なる実装が説明を無視し、コードを使用して事前定義されたメッセージにマッピングすることです。私が作っていたAndroidアプリでこの問題を抱えていたので、説明を設定するだけでなく、メソッドシグネチャを変更して文字列を返すことができました。 Yikes! **それではWCF RESTをこれ以上使用することはありません。** – Aliostad

2

これはIErrorHandlerを実装私のクラスでした。

+0

これは私が行ったことに非常によく似ています。それはRESTサービスのために、あるいはSOAPのためだけに機能しましたか?それがRESTサービスのために働いていた場合、どのようにサービスを設定しましたか? SOAPの場合は、ありがとうございますが、RESTは今のところはまったく別の話です。 –

+1

@Michael私はRESTサービスのためにしました。私は自分でホストされており、実際に自分の派生したサービスホストを作成してその動作を設定しました。すべてのコードベースで、XMLはありません。 –

+0

セルフホスト型、そうです...それは私が考えていたものですが、複雑すぎると考えられています。ありがとう! –

関連する問題