2013-11-25 5 views
7

WCFとC#を使用して既存のSOAP Webサービスにクライアントを構築しました。最近、Webサービスが更新され、クライアントが機能しなくなりました。私がそれを見ている問題は、このブログポストで最もよく説明されています - Interoperability Gotcha: Order of XML Elements Yaron NavehWCF生成プロキシは順序依存であり、サービスはシーケンスに新しい要素を追加しました

私は、私の質問に対してYaronの例を借ります。

<s:element name="root"> 
<s:complexType> 
    <s:sequence> 
    <s:element name="elem1" type="s:string" /> 
    <s:element name="elem2" type="s:string" /> 
    </s:sequence> 
</s:complexType> 
</s:element"> 

は、WCFは、プロキシのような注文明示的な要素を使用し、生成:もともと、WSDLは、ように見えたアップデートで

[XmlElement(Order=0)] 
public string Elem1 
{ 
... 
} 

[XmlElement(Order=1)] 
public string Elem2 
{ 
... 
} 

は、新しい要素を型にに追加されましたが、この要素が追加されましたシーケンスの途中まで。

<s:element name="root"> 
<s:complexType> 
    <s:sequence> 
    <s:element name="elem1" type="s:string" /> 
    <s:element name="NewElement" type="s:string" /> 
    <s:element name="elem2" type="s:string" /> 
    </s:sequence> 
</s:complexType> 
</s:element"> 

私のWCFプロキシは、追加されたNewElementの後に注文された要素を逆シリアル化できません。

Webサービスのプロバイダは、この変更が古いクライアントと下位互換性があると予想していました。どうやら、私のクライアントだけが動作を停止しています。

これはWSDLの大きな変更ですか?

既存のクライアントの破損を防ぐために、シーケンスの最後に新しい要素を追加する必要がありますか?これは後方互換性がありますか?

XmlElement属性でorderパラメータを削除した場合、私のプロキシはこのような将来の変更に対してより適切に準備されますか?注文を取り除くと私は何をあきらめますか?

+0

真ん中にnewElementを追加すると、プロキシが壊れてしまい、大きな変更になりました。これが公正であれば、正確な質問は何ですか? – flup

+0

私は少し質問をreworded。それがより明確であることを願っています。基本的に、私はこれについて二番目の意見が欲しい。私は、サービスの提供者に、彼らの変更が大きな変化であった(彼らはそうではないと思っていた)ことを明確に説明できるようにしたい。私はまた、この変更が急激な変化であるのを防ぐのに役立つ可能性のある代替的な変更を提供したいと思います。私はまた、これらのタイプの変更にどのようにより良い対応ができるかについていくつかアドバイスをしたいと思います。私はたくさんのことを求めていますが、建設的な提案やフィードバックは感謝しています。 –

答えて

10

はい、それはWSDLの大きな変更です。あなたは正しいです、シーケンスの最後に新しい要素を追加すると、下位互換性があります。

消費者が任意の順序で要素を受け入れるようにするには、<xsd:sequence>の代わりに<xsd:all>を使用する必要があります。また、新しい要素を追加したときには、スキーマ定義にminOccurs='0'属性を追加してオプションにしない限り、必須要素です。

<xsd:any>要素を将来の要素のプレースホルダとしてシーケンスの最後に追加することで、スキーマの順方向互換性を高めることもできます。

ご注文インジケータなし
<s:element name="root"> 
<s:complexType> 
    <s:sequence> 
    <s:element name="elem1" type="s:string" /> 
    <s:element name="elem2" type="s:string" /> 
    <s:element name="elem1" type="s:string" /> 
    </s:sequence> 
</s:complexType> 
</s:element"> 

、WCFは知らないだろう。彼らは、その配列内の同じ名前を持つ要素の繰り返しを許可した場合、あなたはあなたのプロキシからの注文を削除する場合に実行することがあり

主な問題はありますどの要素をどのプロパティにマップするかを繰り返します。彼らが.NETやJavaのようなものからXMLを生成しているのであれば、通常は配列やリストを反復する子要素をラップする単一の親要素に変換するので、これは問題ではないでしょう。

<xsd:all>を使用するもう1つの利点は、同じ名前の繰り返し要素が許可されず、この問題が回避されるということです。 <xsd:sequence>には、同じ名前の複数の要素を許可する「機能」があり、リスト内のその位置によってのみ区別されます。

+2

の注文を明示的に指定できます。また、以前の(.NET 2)Web参照に対してテストしました。この動作が存在するかどうかを確認してください。古いWeb参照スタイルのプロキシクラスにはこの問題はありません。したがって、適切な順にオプションは、(1)可能ならば要素をに置き換えます。 (2)従来のAdd Web Referenceを使用してプロキシを生成する。 (3)WCFを使用し、生成されたReference.csクラスを手動で編集してOrderAttributeを "Order = 0"(@ OranDennisonの回答ごとに推奨しない)を削除してください。 –

+2

wsdlをxsd:sequenceの代わりにxsd:allを使うと、配列であったネストされた要素が正しくデシリアライズされていないことがわかりました。ですから、私が第三者に渡した現在のWSDLファイルでは、有効なプロキシクラスを作成するための従来の「Web参照の追加」の方法しか使用できません。 –

0

下位互換性のための最良の方法は、レガシーWebサービスの[Serializable]とは別に[DataContract]と[DataMember]属性を持つ複合型を宣言することです。 DataContractとして宣言することで、複合型にいくつの新しいフィールドが追加されても、クライアントは適切な逆シリアル化されたパラメータを取得します。

+0

プラスDataMembersを使用している場合は、 – CharlesAD

関連する問題