2

カスタム IErrorHandler を備えた REST WCF サービスを使用しているため、サービスでキャッチされていないすべての例外をキャッチし、カスタム エラー メッセージ、適切な HTTP ステータス コード (500) を返し、エラーをログに記録できます。

問題は、IErrorHandler が自分のコードに由来しない例外をキャッチすることです。たとえば、無効な JSON データを使用してサービスに POST を実行すると、SerializationException が発生します。IErrorHandler がなければ、その例外はステータス コード BadRequest 400 の WebFaultException に変換されていたでしょう。そこで、キャッチされていない他のすべての例外と同じように処理します。

これらの状況に対処する方法はありますか、それとも IErrorHandler で SerializationExceptions をキャッチし、そこに BadRequest を設定する必要がありますか? 私のコードからではなく、WCF スタックから発生する可能性のある他の例外は何ですか?

更新: IErrorHandler.ProvideFault の実装を追加しました

 public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        Guid loggingId = Guid.NewGuid();
        error.Data["ExceptionLoggingId"] = loggingId;

        if (error is SecurityTokenException)
        {
            fault = Message.CreateMessage(version, string.Empty, String.Format("{0}. The error identifier is {1}", error.Message, loggingId), new DataContractJsonSerializer(typeof(string)));
            fault.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Json));

            webOperationContextWrapper.SetOutgoingResponseStatusCode(HttpStatusCode.Unauthorized);
        }
        else
        {
            if (error is SerializationException)
            {
                // TODO: What if the SerializationException originates from within the service?
                // SerializationException due to malformed JSON
                return;
            }

            fault = Message.CreateMessage(version, string.Empty, String.Format("An unknown error has occurred. The error identifier is {0}", loggingId), new DataContractJsonSerializer(typeof(string)));
            fault.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Json));

            webOperationContextWrapper.SetOutgoingResponseStatusCode(HttpStatusCode.InternalServerError);
        }
}
4

2 に答える 2

1

同様の問題に遭遇しました。

私の解決策は、名前空間を使用して例外の原因を特定することでした。

if (!error.StackTrace.TrimStart().StartsWith("at " + this.GetType().Namespace.Split('.')[0]))
    return;

これは私の現在のプロジェクトで機能します。ただし、プロジェクトによっては、そうでない場合があります...

于 2011-11-07T20:17:51.457 に答える
0

@RichardBlewettは正しいと思います。カスタム例外クラスを作成してそれをスローし、エラー ハンドラーでその型をチェックしてから、標準のシリアライゼーション例外が正常に流れるようにする必要があります。それは私にとって最高のデザインパターンのようです。

次に、削除または変更すると、エラー ハンドラー コードがコンパイルされないか、VS 経由で行うとその型でリファクタリングされるタイプ セーフな例外が発生します。名前空間をそのようにテストすることは、コンパイル時にどの型にも直接関連付けられていないため、(非常に巧妙ではありますが) あまりお勧めできません。名前空間を変更すると、追跡が困難な問題が発生します。

于 2012-08-29T20:48:11.497 に答える