MessageContracts を使用する WCF サービスがあります。頭を悩ませているのは、メッセージ内の要素の順序が変更されると、サービスがその要素を無視することです。以下に例を示します (関係のない詳細は削除されています)。
<soapenv:Envelope ...>
<soapenv:Header/>
<soapenv:Body>
<bci:MySampleRequest>
<bci:Apples>some value here</bci:Apples>
<bci:Bananas>another value here</bci:Bananas>
<bci:Oranges>something else</bci:Oranges>
</bci:MySampleRequest>
</soapenv:Body>
</soapenv:Envelope>
それはうまくいきます。しかし、代わりに私が送信した場合
<soapenv:Envelope ...>
<soapenv:Header/>
<soapenv:Body>
<bci:MySampleRequest>
<bci:Bananas>another value here</bci:Bananas>
<bci:Apples>some value here</bci:Apples>
<bci:Oranges>something else</bci:Oranges>
</bci:MySampleRequest>
</soapenv:Body>
</soapenv:Envelope>
Bananas の値は無視され、NULL として返されます。私の MessageContract クラスは次のようになります。
[WCF::MessageContract(WrapperName = "MySampleRequest", WrapperNamespace = "...")]
public partial class MySampleRequest {
private string bananas;
private string apples;
private string oranges;
[WCF::MessageBodyMember(Namespace = "...", Name = "Bananas")]
public string Bananas {
get { return effectiveDate; }
set { effectiveDate = value; }
}
[WCF::MessageBodyMember(Namespace = "...", Name = "Apples")]
public string Apples {
get { return apples; }
set { apples = value; }
}
[WCF::MessageBodyMember(Namespace = "...", Name = "Oranges")]
public string Oranges {
get { return oranges; }
set { oranges = value; }
}
}
また、DataContractSerializer を使用していることにも言及する必要があります。ここでの例は単純な文字列ですが、実際のメッセージ オブジェクトははるかに複雑で、リストと DataContract オブジェクトが含まれています。
WCF はデフォルトでメンバーをアルファベット順に並べているようです。正直なところ、どの順序が使用されているかさえ気にしません。私が望むのは、消費者がこれらの値を好きな順序で渡して、サービスを引き続き機能させることができるようにすることです。XMLは順序が指定されていなくても読みやすいので、これは実行できそうです。
シリアライザーを変更したり、MessageContract から DataContract に変更したりしたくないことに注意してください。これは、実稼働環境の既存のサービスであり、WSDL が既存のコードと互換性がなくなるような変更を行うことはできません。これらの MessageContract を DataContract に変更して遊んだところ、WSDL の構造が変更され、既存のコードと互換性がなくなりました。