SOAPエラーメッセージ内の複数の名前空間により、FaultExceptionの逆シリアル化が失敗する

StackOverflow https://stackoverflow.com/questions/1441647

質問

Webサービスに接続していますが、返される障害メッセージは(まったく)逆シリアル化されておらず、作成できるクラスのバージョンは正しく逆シリアル化されません。サーバー側を制御することはできません。サーバーは検出を許可しないため、エンドポイントのURLの最後に?WSDLを追加すると、WSDLではなくエラーが発生します。

[Fiddler] [1]は、次のようなエラーメッセージが表示されることを示しています。

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:eGov="http://eGov.gov" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <soapenv:Fault>
    <faultcode>Client</faultcode>
    <faultstring/>
      <detail>
        <eGov:eGov2Exception>
          <eGov:ErrorClassification>SOME_ERROR</eGov:ErrorClassification>
          <eGov:ErrorCode>SOME_ERROR_CODE</eGov:ErrorCode>
          <eGov:ErrorMessage>Your request was unsuccessful. blah blah blah.</eGov:ErrorMessage>
        </eGov:eGov2Exception>
      </detail>
    </soapenv:Fault>
  </soapenv:Body>
</soapenv:Envelope>

作成したクラス(xsd.exe、svcutil、およびゼロから作成したコードを含む他のものを試してみてください)では、キャッチしようとしたときにデシリアライズできません:

catch (FaultException<eGov2ExceptionType> exp)
  {
     // Never stops here. 
  }
catch (FaultException<AllOtherAttemptedClasses> exp)
  {
     // Never stops here. 
  }
catch (SoapException se)
  {
     // Never stops here. 
  }
catch (FaultException exp)
  {
     //Always gets caught here. 
  }

ベースのFaultExceptionキャッチのみが呼び出されます。つまり、送信されているFaultMessageの内容が失われます。私が書いたクラスのいくつかは、上記のサンプルに非常に密接にシリアライズされますが、デシリアライズに失敗するため、私たちの疑いは、名前空間の問題があることです。

質問:

1-これをどのように書きますか?

2-これはWCFの一般的なエラー/問題ですか?

[1]: http://www.fiddler2.com/fiddler2/ Fiddler

役に立ちましたか?

解決

私たちがやったことは、 Fault をキャッチしてSOAPチャネルに返そうとするのをやめることでした。代わりに、カスタム例外を作成し、 MessageInspector を接続して障害を監視し、例外としてスローします。

(サニタイズされた)コードの関連部分:

   public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        if (reply.IsFault)
        {
            XmlDictionaryReader xdr = reply.GetReaderAtBodyContents();
            XNode xn = XDocument.ReadFrom(xdr);
            string s = xn.ToString();
            XDocument xd = XDocument.Parse(s);
            XNamespace nsSoap = "http://schemas.xmlsoap.org/soap/envelope/";
            XNamespace ns = "http://eGov.gov";
            XElement xErrorClass = xd.Element(nsSoap + "Fault").Element("detail").Element(ns + "eGov2Exception").Element(ns + "RequestErrorClassification");
            XElement xErrorCode = xd.Element(nsSoap + "Fault").Element("detail").Element(ns + "eGov2Exception").Element(ns + "RequestErrorCode");
            XElement xErrorMessage = xd.Element(nsSoap + "Fault").Element("detail").Element(ns + "eGov2Exception").Element(ns + "RequestErrorMessage");

            throw new eGovException(xErrorClass.Value, xErrorCode.Value, xErrorMessage.Value);
        }
    }

メインアプリケーションは次を使用します:

catch(eGovException ex)
  {
    //ここで例外を処理します。
  }

名前空間を修正するために多くの時間が浪費されました。回答ありがとうございます。

他のヒント

シリアル化が完全に失敗した場合にこれを処理する1つの方法は、メッセージを入力および出力として入力します。この方法では、Iffault == trueのときにXMLを手動で解析するか、GetBody()を使用してエラーが発生しなかった場合に通常のコンテンツを取得できます。

まず、このWebサービスを作成した人々からWSDLを取得できない場合、SOAPベースのWebサービスを持つビジネスはありません。適切なWSDLは、「?WSDL」かどうかにかかわらず、問題を解決します。使用されます。

次に、 eGov2ExceptionType クラスのコードを投稿してください。 http://eGov.gov 名前空間が設定されていないようです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top