0

IIS でホストされ、WS HTTP バインディング (外部サービス) を使用する WCF サービスがあります。このサービスは、Net TCP (内部サービス) を介して、Windows サービスでホストされている 2 番目の WCF サービスを呼び出すことになります。内部サービスが をスローするFaultExceptionと、クライアントにスローするのではなく、外部サービスがクラッシュします。クライアントが見るのは、接続が強制的に閉じられていることだけです。

内部サービスは、Enterprise Library Validation Application Block を使用して受信メッセージを検証します。検証エラーが発生すると、サービスはFaultException<ValidationFault>.

内部サービスと外部サービスの両方が[FaultContract(typeof(ValidationFault)]、サービス コントラクトに属性を持っています。外部サービスをすぐに new をスローするように変更するとFaultException<ValidaitonFault>、これはクライアントに問題なく返されます。内部サービスからの例外を外部サービスでキャッチできますが、再スローしようとしたり、新しい例外でラップしてスローしたりすると、IIS のアプリケーション プール全体がクラッシュします。イベント ログに役立つ情報が何も表示されないため、何が問題なのか正確にはわかりません。

外部サービスが内部サービスとの通信に使用するクライアント オブジェクトは、確実に閉じられ、正しく破棄されています。内部サービスの障害をクライアントに伝播するにはどうすればよいですか?

更新しました:

以下は、外部サービス コードの簡略版です。内部サービス呼び出しから検証エラーをキャッチできます。新品を投げればFaultException<ValidationFault>大丈夫です。キャッチされた例外を使用すると、外部クライアントへの接続が切断されます。私が見ることができる唯一の違いは、サービスをデバッグするときです-キャッチされた例外を使用しようとすると、メソッドを終了するときにメッセージボックスが表示されます。

タイプ 'System.ServiceModel.FaultException`1' の未処理の例外が mscorlib.dll で発生しました

まったく新しい例外をスローすると、これは表示されません。おそらく答えは、検証エラーの詳細を新しいオブジェクトに手動でコピーすることですが、これはおかしいようです。

public class ExternalService : IExternalService
{
   public ExternalResponse DoSomething(ExternalRequest)
   {
      try
      {
         var response = new ExternalResponse();
         using (var internalClient = new InternalClient())
         {
            response.Data = internalClient.DoSomething().Data;
         }

         return response;
      }
      catch (FaultException<ValidationFault> fEx)
      {
         // throw fEx;   <- crashes

         // throw new FaultException<ValidationFault>(
         //    fEx.Detail as ValidationFault);   <- crashses

         throw new FaultException<ValidationFault>(
            new ValidationFault(new List<ValidationDetail> {
               new ValidationDetail("message", "key", "tag") }),
               "fault message", new FaultCode("faultCode"))); // works fine!
      }
   }
}
4

2 に答える 2

0

まあ、これをやればうまくいきますが、もっと良い方法があるはずです...

これは のみの問題のようですFaultException<ValidationFault>。再投げFaultExceptionFaultException<SomethingElse>問題なくできます。

try
{
   DoStuff();
}
catch (FaultException<ValidationFault> fe)
{
   throw this.HandleFault(fe);
}

...

private FaultException<ValidationFault> HandleFault(
    FaultException<ValidationFault> fex)
{
    var validationDetails = new List<ValidationDetail>();
    foreach (ValidationDetail detail in fex.Detail.Details)
    {
        validationDetails.Add(detail);
    }

    return new FaultException<ValidationFault>(
        new ValidationFault(validationDetails));
}
于 2010-08-04T08:30:02.817 に答える
0

私はあなたとほぼ同じ設計をしており、同様の問題に遭遇しました(ただし、クラッシュについてはわかりません!)。

私の記憶が正しければValidationFault、Fault がネットワーク上を移動するときのクラスは共通ですが、型は WCF インターフェイスに固有のものです。これは、Web サービスの名前空間修飾子が原因だと思います (ただし、これは少し前のことなので、間違っている可能性があります)。

それほどエレガントではありませんが、私がしたことは手動で例外を再スローすることでした:

try
{
    DoStuff();
}
catch (FaultException<ValidationFault> fe)
{
    HandleFault(fe);
    throw;
}

...

private void HandleFault(FaultException<ValidationFault> fe)
{
    throw new FaultException<ValidationFault>(fe.Detail as ValidationFault);
}
于 2010-08-03T22:55:18.450 に答える