2

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

[Fiddler][1] は、Fault メッセージが次のように戻ってくることを示しています。

<?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/フィドラー

4

3 に答える 3

4

最終的にやったのは、 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)
{
// ここで例外を処理します。
}

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

于 2009-09-25T18:03:06.543 に答える
1

まず第一に、このWebサービスを作成した人々からWSDLを入手できない場合、彼らはSOAPベースのWebサービスを持っているビジネスを持っていません。「?WSDL」が使用されているかどうかに関係なく、適切なWSDLで問題が解決します。

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

于 2009-09-19T20:19:10.390 に答える
1

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

于 2009-09-18T08:02:10.770 に答える