4
  • 既存のサービスを変更して追加のデータメンバーを追加していることに注意してください。サービスの構造もクライアントも変更できません。ASMX が時代遅れであり、ベスト プラクティスが使用されていないことはわかっています。

非常に奇妙な問題に遭遇しました。これを適切に機能させる方法がわかりません。私はASMX Webサービスを持っています(私はそれが古くなっていることを知っています、私はこれを変更できません)それは応答を受け取り、それをzip圧縮で圧縮します。次に、SOAP を介してクライアントに配信され、クライアントはストリームを取得して解凍し、「サービス参照の追加」によって作成されたコントラクトと XMLSerializer を使用してオブジェクトを逆シリアル化します。

私が抱えている問題は、オブジェクトを正しく逆シリアル化できないことです。圧縮前と圧縮解除後の XML はまったく同じように見えますが、Web サービスがパラメータの順序を無視しているようです。[DataMember] 、 [MessageBodyMember]、[XmlElement]、[MessageHeader] をすべて正しい順序付けパラメーターと MustUnderstand で試しましたが、常に XML の下部に要素を貼り付けているようです。

これが紛らわしいものです。私のメッセージコントラクトクラスは、別のメッセージコントラクトクラスから継承しています

[MessageContract(IsWrapped = true)]
public class MyClass : MyBaseContract{}

ベースコンタクトの要素は、毎回問題なくデシリアライズされますが、それらを変更しても問題なく動作します。そこの要素には順序がまったく含まれておらず、機能します。

これが私の逆シリアル化コードです。

using (MemoryStream stream = new MemoryStream(data))
        {
            XDocument document = XDocument.Load(stream);

            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(type);
            System.Xml.XmlReader read = System.Xml.XmlReader.Create(new System.IO.StringReader(document.ToString()));

            object o = serializer.Deserialize(read);

            return o;
        }

シリアル化コードは次のとおりです。

        XmlSerializer xs = new XmlSerializer(value.GetType());
        MemoryStream stream = new MemoryStream();
        xs.Serialize(stream, value);
        stream.Position = 0;
        StreamReader sr = new StreamReader(stream);
        return sr.ReadToEnd();

だからここに私のコードが取るステップがあります

  1. Web サービスへの呼び出し
  2. Web サービスがヘルパーを呼び出し、応答オブジェクトを返す
  3. 応答オブジェクトは圧縮されています
  4. 圧縮されたオブジェクトは、ネットワーク経由で SOAP 形式で送信されます
  5. クライアントが応答を受け取る
  6. クライアントは、「サービス参照の追加」機能から提供されたコントラクトに基づいて逆シリアル化します。
  7. クライアントは応答の基本クラスからデータを逆シリアル化できますが、応答クラス自体からは何も逆シリアル化されません。
4

1 に答える 1

2

私はそれを解決しましたが、それは本当に厄介です。

発生したのは、「サービス参照の追加」生成コードに名前空間別名が含まれていることです

    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://myservice.com")]

ただし、手動で実行できる XML シリアル化では、生成された XML のどこにも名前空間が含まれません。このコードを使用して指定すると、XML シリアライザーが壊れます。

   [MessageContract(IsWrapped = true,WrapperNamespace="http://myservice.com")]

適切に動作させる唯一の方法は、生成されたコードから名前空間を指定する行を、そのようにコントラクト クラスに追加することです。

[XmlType(Namespace="http://myservice.com")]
public class MyContract {}

この追加の後、生成されたすべての xml には各要素に完全な名前空間が含まれ、デシリアライザーは適切に動作します。名前空間の WCF ism で壊れる理由がわかりません。他の WCF isms では問題なく動作します。

そもそも部分的に機能していた理由は、以前の開発者が、クライアント側の特定の XML 要素に名前空間を手動で挿入するメソッドを追加したためです。具体的には、正しく機能していた基本クラスのものです! メソッドが非常に深く埋もれているため、メソッドが呼び出されているのを見ませんでした。

于 2013-09-25T15:58:54.537 に答える