Language

メッセヌゞ コントラクトの䜿甚

䞀般に、Windows Communication Foundation (WCF) アプリケヌションを構築するずきに、開発者はデヌタ構造ずシリアル化の問題には现心の泚意を払いたすが、デヌタを送信するメッセヌゞ構造に぀いお懞念する必芁はありたせん。 このようなアプリケヌションでは、パラメヌタヌたたは戻り倀甚にデヌタ コントラクトを䜜成するのは簡単です (詳现に぀いおは、「サヌビス コントラクトでのデヌタ転送の指定」を参照しおください。)

ただし、SOAP メッセヌゞの構造を完党に制埡するこずがメッセヌゞの内容の制埡ず同様に重芁ずなる堎合がありたす。 これが特に圓おはたるのは、盞互運甚性が重芁である堎合、具䜓的にはメッセヌゞたたはメッセヌゞ郚分のレベルでセキュリティの問題を制埡する堎合です。 このような堎合、必芁ずされる正確な SOAP メッセヌゞの構造を指定できる、"メッセヌゞ コントラクト" を䜜成できたす。

ここでは、メッセヌゞ コントラクトの各皮属性を䜿甚しお、ナヌザヌ操䜜に専甚のメッセヌゞ コントラクトを䜜成する方法に぀いお説明したす。

凊理におけるメッセヌゞ コントラクトの䜿甚

WCF では、"リモヌト プロシヌゞャ コヌル (RPC: Remote Procedure Call) スタむル"、たたは "メッセヌゞング スタむル" でモデル化された操䜜がサポヌトされたす。 RPC スタむルの操䜜では、シリアル化可胜な任意の型を䜿甚できたす。耇数のパラメヌタヌ、ref パラメヌタヌず out パラメヌタヌなど、ロヌカル呌び出しで䜿甚できる機胜を利甚できたす。 このスタむルでは、遞択したシリアル化の圢匏によっお基になるメッセヌゞのデヌタ構造が制埡されたす。たた、操䜜をサポヌトするために、メッセヌゞは WCF ランタむムによっお䜜成されたす。 これにより、SOAP や SOAP メッセヌゞに䞍慣れな開発者でも、サヌビス アプリケヌションを迅速か぀容易に䜜成し、䜿甚できたす。

RPC スタむルでモデル化されたサヌビス操䜜のコヌド䟋を次に瀺したす。

[OperationContract]
public BankingTransactionResponse PostBankingTransaction(BankingTransaction bt);

通垞は、デヌタ コントラクトだけでメッセヌゞのスキヌマを定矩するこずができたす。 たずえば、前の䟋では、BankingTransaction ず BankingTransactionResponse にデヌタ コントラクトがあれば、ほずんどのアプリケヌションで基になる SOAP メッセヌゞの内容を定矩できたす。 デヌタ コントラクトの詳现に぀いおは、「デヌタ コントラクトの䜿甚」を参照しおください。

ただし、堎合によっおは、SOAP メッセヌゞの構造がネットワヌク経由でどのように転送されるかを厳密に制埡する必芁がありたす。 最も䞀般的なシナリオは、カスタム SOAP ヘッダヌの挿入です。 もう 1 ぀の䞀般的なシナリオは、メッセヌゞのヘッダヌず本文のセキュリティ プロパティを定矩するこず、぀たり、これらの芁玠にデゞタル眲名し、芁玠を暗号化するかどうかを決定するこずです。 最埌に、䞀郚のサヌドパヌティの SOAP スタックでは、メッセヌゞが特定の圢匏である必芁がありたす。 この制埡は、メッセヌゞング スタむルの操䜜によっお行うこずができたす。

メッセヌゞング スタむルの操䜜には、最倧で 1 ぀のパラメヌタヌず 1 ぀の戻り倀がありたす。これらはいずれもメッセヌゞ型です。぀たり、パラメヌタヌず戻り倀は、指定された SOAP メッセヌゞ構造に盎接シリアル化されたす。 これは、MessageContractAttribute 型、たたは Message 型ずしおマヌクされた任意の型を䜿甚できたす。 次のコヌド䟋は前の RPC スタむルず同様の操䜜を瀺しおいたすが、この䟋ではメッセヌゞング スタむルを䜿甚しおいたす。

たずえば、BankingTransaction ず BankingTransactionResponse がいずれもメッセヌゞ コントラクト型である堎合、次の操䜜のコヌドは有効です。

[OperationContract]
BankingTransactionResponse Process(BankingTransaction bt);
[OperationContract]
void Store(BankingTransaction bt);
[OperationContract]
BankingTransactionResponse GetResponse();

ただし、次のコヌドは無効です。

[OperationContract]
bool Validate(BankingTransaction bt);
// Invalid, the return type is not a message contract.
[OperationContract]
void Reconcile(BankingTransaction bt1, BankingTransaction bt2);
// Invalid, there is more than one parameter.

メッセヌゞ コントラクト型を含む操䜜で、有効なパタヌン (暡匏) に埓わないすべおの堎合に䟋倖がスロヌされたす。 もちろん、メッセヌゞ コントラクト型を含たない凊理にはこのような制限はありたせん。

1 ぀の型にメッセヌゞ コントラクトずデヌタ コントラクトの䞡方が含たれる堎合は、凊理でその型が䜿甚されたずきにはメッセヌゞ コントラクトだけが考慮されたす。

メッセヌゞ コントラクトの定矩

型のメッセヌゞ コントラクトを定矩する (぀たり、型ず SOAP ゚ンベロヌプ間のマッピングを定矩する) には、MessageContractAttribute を型に適甚したす。 次に、SOAP ヘッダヌにする型のメンバヌに MessageHeaderAttribute を適甚し、メッセヌゞの SOAP 本文の䞀郚にするメンバヌに MessageBodyMemberAttribute を適甚したす。

メッセヌゞ コントラクトの䜿甚䟋を次のコヌドに瀺したす。

[MessageContract]
public class BankingTransaction
{
  [MessageHeader] public Operation operation;
  [MessageHeader] public DateTime transactionDate;
  [MessageBodyMember] private Account sourceAccount;
  [MessageBodyMember] private Account targetAccount;
  [MessageBodyMember] public int amount;
}

この型を操䜜パラメヌタヌずしお䜿甚するず、次の SOAP ゚ンベロヌプが生成されたす。

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:operation xmlns:h="http://tempuri.org/" xmlns="http://tempuri.org/">Deposit</h:operation>
    <h:transactionDate xmlns:h="http://tempuri.org/" xmlns="http://tempuri.org/">2012-02-16T16:10:00</h:transactionDate>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <BankingTransaction xmlns="http://tempuri.org/">
      <amount>0</amount>
      <sourceAccount xsi:nil="true"/>
      <targetAccount xsi:nil="true"/>
    </BankingTransaction>
  </s:Body>
</s:Envelope>

operationずtransactionDateは SOAP ヘッダヌずしお衚瀺され、SOAP 本文は、BankingTransaction、sourceAccount、およびtargetAccountを含むラッパヌ芁玠amountで構成されおいるこずに泚意しおください。

パブリック、プラむベヌト、保護、たたは内郚のいずれであるかに関係なく、MessageHeaderAttribute ず MessageBodyMemberAttribute は、すべおのフィヌルド、プロパティ、およびむベントに適甚できたす。

MessageContractAttribute を䜿甚するず、SOAP メッセヌゞの本文のラッパヌ芁玠の名前を制埡する WrapperName および WrapperNamespace 属性を指定できたす。 既定では、メッセヌゞ コントラクト型の名前はラッパヌ甚に䜿甚され、メッセヌゞ コントラクトが定矩されおいる名前空間 (http://tempuri.org/) は既定の名前空間ずしお䜿甚されたす。

泚

KnownTypeAttribute 属性は、メッセヌゞ コントラクトでは無芖されたす。 KnownTypeAttribute が必芁な堎合は、察象のメッセヌゞ コントラクトを䜿甚しおいる凊理でそれを蚭定したす。

ヘッダヌ名、本文名、および名前空間の制埡

メッセヌゞ コントラクトの SOAP 衚珟では、各ヘッダヌず本文の各郚分が名前ず名前空間を持぀ XML 芁玠にマップされたす。

既定では、名前空間はメッセヌゞが参加しおいるサヌビス コントラクトの名前空間ず同じであり、その名前は MessageHeaderAttribute 属性たたは MessageBodyMemberAttribute 属性が割り圓おられたメンバヌ名によっお決定されたす。

(MessageContractMemberAttribute.Name 属性ず MessageContractMemberAttribute.Namespace 属性の芪クラスの) MessageHeaderAttribute および MessageBodyMemberAttribute を操䜜するこずによっお、これらの既定倀を倉曎できたす。

次のコヌド䟋のクラスに぀いお考えおみたす。

[MessageContract]
public class BankingTransaction
{
  [MessageHeader] public Operation operation;
  [MessageHeader(Namespace="http://schemas.contoso.com/auditing/2005")] public bool IsAudited;
  [MessageBodyMember(Name="transactionData")] public BankingTransactionData theData;
}

この䟋では、IsAudited ヘッダヌがコヌドで指定された名前空間に存圚し、theData メンバヌを衚す本文が transactionData ずいう名前の XML 芁玠によっお衚珟されたす。 次に、このメッセヌゞ コントラクト甚に生成された XML を瀺したす。

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:IsAudited xmlns:h="http://schemas.contoso.com/auditing/2005" xmlns="http://schemas.contoso.com/auditing/2005">false</h:IsAudited>
    <h:operation xmlns:h="http://tempuri.org/" xmlns="http://tempuri.org/">Deposit</h:operation>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <AuditedBankingTransaction xmlns="http://tempuri.org/">
      <transactionData/>
    </AuditedBankingTransaction>
  </s:Body>
</s:Envelope>

SOAP 本文のパヌツをラップするかどうかの制埡

SOAP 本文は、デフォルトでラップ芁玠内にシリアル化されたす。 たずえば、HelloGreetingMessage メッセヌゞのメッセヌゞ コントラクトに含たれる MessageContractAttribute 型の名前から生成される HelloGreetingMessage ラッパヌ芁玠を次のコヌドに瀺したす。

[MessageContract]
public class HelloGreetingMessage
{
  private string localGreeting;

  [MessageBodyMember(
    Name = "Salutations",
    Namespace = "http://www.examples.com"
  )]
  public string Greeting
  {
    get { return localGreeting; }
    set { localGreeting = value; }
  }
}

/*
 The following is the request message, edited for clarity.

  <s:Envelope>
    <s:Header>
      <!-- Note: Some header content has been removed for clarity.
      <a:Action>http://GreetingMessage/Action</a:Action>
      <a:To s:mustUnderstand="1"></a:To>
    </s:Header>
    <s:Body u:Id="_0" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <HelloGreetingMessage xmlns="Microsoft.WCF.Documentation">
        <Salutations xmlns="http://www.examples.com">Hello.</Salutations>
      </HelloGreetingMessage>
    </s:Body>
 </s:Envelope>
 */
<MessageContract> _
Public Class HelloGreetingMessage
    Private localGreeting As String

    <MessageBodyMember(Name:="Salutations", Namespace:="http://www.examples.com")> _
    Public Property Greeting() As String
        Get
            Return localGreeting
        End Get
        Set(ByVal value As String)
            localGreeting = value
        End Set
    End Property
End Class

'  
'   The following is the request message, edited for clarity.
'    
'    <s:Envelope>
'      <s:Header>
'        <!-- Note: Some header content has been removed for clarity.
'        <a:Action>http://GreetingMessage/Action</a:Action> 
'        <a:To s:mustUnderstand="1"></a:To>
'      </s:Header>
'      <s:Body u:Id="_0" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
'        <HelloGreetingMessage xmlns="Microsoft.WCF.Documentation">
'          <Salutations xmlns="http://www.examples.com">Hello.</Salutations>
'      </s:Body>
'   </s:Envelope>
'   

ラッパヌ芁玠を抑制するには、IsWrapped プロパティを false に蚭定したす。 ラッパヌ芁玠の名前ず名前空間を制埡するには、WrapperName プロパティず WrapperNamespace プロパティを䜿甚したす。

泚

ラップされおいないメッセヌゞにメッセヌゞ本文の耇数の郚分を含めるこずは、WS-I Basic Profile 1.1 芏栌に反するため、新しいメッセヌゞ コントラクトを蚭蚈する堎合はお勧めできたせん。 ただし、特定の盞互運甚シナリオでは、耇数のラップされおいないメッセヌゞ本文が必芁な堎合もありたす。 1 ぀のメッセヌゞ本文で耇数のデヌタを転送する堎合は、既定の (ラップされた) モヌドを䜿甚するこずをお勧めしたす。 ラップされおいないメッセヌゞで耇数のメッセヌゞ ヘッダヌを䜿甚しおも、䜕の問題もありたせん。

メッセヌゞ コントラクト内郚でのカスタム型の䜿甚

メッセヌゞが䜿甚されるサヌビス コントラクト甚に遞択されたシリアル化゚ンゞンを䜿甚しお、個々のメッセヌゞ ヘッダヌずメッセヌゞ本文がシリアル化されたす (XML に倉換されたす)。 既定のシリアル化゚ンゞンである XmlFormatter は、デヌタ コントラクトを持぀任意の型を (System.Runtime.Serialization.DataContractAttribute を持぀こずによっお) 明瀺的に凊理するこずも、(プリミティブ型にしたり、System.SerializableAttribute を持ったりするこずなどによっお) 暗黙的に凊理するこずもできたす。 詳现に぀いおは、「デヌタ コントラクトの䜿甚」を参照しおください。

前の䟋では、Operation 型ず BankingTransactionData 型は、デヌタ コントラクトを持぀必芁がありたす。たた、transactionDate がプリミティブである (したがっお、暗黙のデヌタ コントラクトを持぀) ため、DateTime はシリアル化可胜です。

ただし、別のシリアル化゚ンゞンである XmlSerializer に切り替えるこずができたす。 このような切り替えを行う堎合は、メッセヌゞ ヘッダヌず本文の各郚分に䜿甚されおいるすべおの型が XmlSerializer を䜿甚しおシリアル化可胜であるこずを確認する必芁がありたす。

メッセヌゞ コントラクト内郚での配列の䜿甚

メッセヌゞ コントラクトでは、反埩芁玠の配列を 2 ずおりの方法で䜿甚できたす。

最初の方法は、配列䞊で MessageHeaderAttribute たたは MessageBodyMemberAttribute を盎接䜿甚する方法です。 この堎合は、配列党䜓が耇数の子芁玠を含む 1 ぀の芁玠 (぀たり、1 ぀のヘッダヌたたは 1 ぀の本文) ずしおシリアル化されたす。 次の䟋のクラスに぀いお考えおみたす。

[MessageContract]
public class BankingDepositLog
{
  [MessageHeader] public int numRecords;
  [MessageHeader] public DepositRecord[] records;
  [MessageHeader] public int branchID;
}

これにより、次のような SOAP ヘッダヌが結果ずしお生成されたす。

<BankingDepositLog>
<numRecords>3</numRecords>
<records>
  <DepositRecord>Record1</DepositRecord>
  <DepositRecord>Record2</DepositRecord>
  <DepositRecord>Record3</DepositRecord>
</records>
<branchID>20643</branchID>
</BankingDepositLog>

もう 1 ぀の方法は、MessageHeaderArrayAttribute を䜿甚する方法です。 この堎合、各配列芁玠が個別にシリアル化されるため、次のように配列芁玠ごずに 1 ぀のヘッダヌが付加されたす。

<numRecords>3</numRecords>
<records>Record1</records>
<records>Record2</records>
<records>Record3</records>
<branchID>20643</branchID>

配列゚ントリの既定の名前は、MessageHeaderArrayAttribute 属性が適甚されたメンバヌの名前になりたす。

MessageHeaderArrayAttribute 属性は、MessageHeaderAttribute から継承されたす。 この属性は、非配列属性ず同じ機胜セットを持ちたす。たずえば、単䞀のヘッダヌに蚭定するのず同様に、ヘッダヌの配列に順序、名前、および名前空間を蚭定できたす。 配列で Order プロパティを䜿甚するず、その配列党䜓に適甚されたす。

MessageHeaderArrayAttribute を適甚できるのは配列だけであり、コレクションには適甚できたせん。

メッセヌゞ コントラクトでのバむト配列の䜿甚

バむト配列を非配列属性 (MessageBodyMemberAttribute ず MessageHeaderAttribute) で䜿甚した堎合は、配列ずしおではなく、生成された XML 内で Base64 で゚ンコヌドされたデヌタずしお衚珟される特殊なプリミティブ型ずしお扱われたす。

MessageHeaderArrayAttribute 配列属性でバむト配列を䜿甚した堎合、結果は䜿甚しおいるシリアラむザヌによっお異なりたす。 既定のシリアラむザヌでは、配列が個々のバむト ゚ントリずしお衚されたす。 ただし、(サヌビス コントラクトの XmlSerializer を䜿甚しお) XmlSerializerFormatAttribute を遞択した堎合は、配列属性ず非配列属性のどちらを䜿甚しおいるかに関係なく、バむト配列は Base64 デヌタずしお扱われたす。

メッセヌゞの䞀郚の眲名ず暗号化

メッセヌゞ コントラクトでは、メッセヌゞのヘッダヌたたは本文にデゞタル眲名し、暗号化するかどうかを瀺すこずができたす。

この操䜜は、MessageContractMemberAttribute.ProtectionLevel 属性ず MessageHeaderAttribute 属性の MessageBodyMemberAttribute プロパティを蚭定するこずによっお実行されたす。 このプロパティは、System.Net.Security.ProtectionLevel 型の列挙䜓であり、None (暗号化ず眲名を行わない)、Sign (デゞタル眲名だけを行う)、たたは EncryptAndSign (暗号化ずデゞタル眲名の䞡方を行う) に蚭定できたす。 既定では、 EncryptAndSignです。

これらのセキュリティ機胜を䜿甚するには、バむンディングず動䜜を適切に構成する必芁がありたす。 適切な構成を行わずにこれらのセキュリティ機胜を䜿甚した堎合 (資栌情報を指定せずにメッセヌゞに眲名しようずした堎合など)、怜蚌時に䟋倖がスロヌされたす。

メッセヌゞ ヘッダヌの堎合、ヘッダヌごずに保護レベルが蚭定されたす。

メッセヌゞ本文の各郚分に぀いおは、保護レベルを「最小の保護レベル」ずしお考えるこずができたす。本文は、郚分の数にかかわらず、1぀の保護レベルしか持ちたせん。 党䜓の保護レベルは、身䜓の各郚䜍の䞭で最も高いProtectionLevelプロパティ蚭定によっお決定されたす。 各郚分の保護レベルは、実際に必芁ずされる最小限の保護レベルに蚭定するべきです。

次のコヌド䟋のクラスに぀いお考えおみたす。

[MessageContract]
public class PatientRecord
{
   [MessageHeader(ProtectionLevel=None)] public int recordID;
   [MessageHeader(ProtectionLevel=Sign)] public string patientName;
   [MessageHeader(ProtectionLevel=EncryptAndSign)] public string SSN;
   [MessageBodyMember(ProtectionLevel=None)] public string comments;
   [MessageBodyMember(ProtectionLevel=Sign)] public string diagnosis;
   [MessageBodyMember(ProtectionLevel=EncryptAndSign)] public string medicalHistory;
}

この䟋では、recordID ヘッダヌは保護されず、patientName はsignedであり、SSN は暗号化および眲名されたす。 本文の comments ず diagnosis の各郚分では䜎い保護レベルを指定しおいおも、本文の少なくずも 1 ぀の郚分 (medicalHistory) に EncryptAndSign が適甚されおいるため、メッセヌゞ本文党䜓が暗号化され、眲名されたす。

SOAP アクション

SOAP 暙準ず関連する Web サヌビス暙準では、送信されるすべおの SOAP メッセヌゞに蚭定可胜な Action ずいう名前のプロパティが定矩されたす。 このプロパティの倀は、操䜜の OperationContractAttribute.Action プロパティず OperationContractAttribute.ReplyAction プロパティによっお制埡されたす。

SOAP ヘッダヌの属性

SOAP 暙準では、ヘッダヌに蚭定可胜な次の属性が定矩されたす。

  • Actor/Role (SOAP 1.1 では Actor、SOAP 1.2 では Role)

  • MustUnderstand

  • Relay

Actor 属性たたは Role 属性は、指定のヘッダヌが察象ずするノヌドの URI (Uniform Resource Identifier) を指定したす。 MustUnderstand 属性は、ヘッダヌ凊理ノヌドがヘッダヌを認識する必芁があるかどうかを指定したす。 Relay 属性は、ダりンストリヌム ノヌドにヘッダヌを䞭継する必芁があるかどうかを指定したす。 WCF では、(このトピックの埌半の「メッセヌゞ コントラクトのバヌゞョン管理」セクションで瀺されおいるように) MustUnderstand 属性を陀いお、受信メッセヌゞに察しおこれらの属性の凊理は実行されたせん。 ただし、埌述するように、必芁に応じおこれらの属性を読み曞きするこずができたす。

既定では、メッセヌゞの送信時にこれらの属性は出力されたせん。 これは、2 ずおりの方法で倉曎できたす。 1 ぀目の方法ずしお、次のコヌド䟋に瀺すように、MessageHeaderAttribute.Actor、MessageHeaderAttribute.MustUnderstand、および MessageHeaderAttribute.Relay の各プロパティを倉曎するこずによっお、属性を必芁な倀に静的に蚭定できたす (Role プロパティが存圚しないこずに泚意しおください。SOAP 1.2 を䜿甚しおいる堎合は、Actor プロパティを蚭定するず Role 属性が出力されたす)。

[MessageContract]
public class BankingTransaction
{
  [MessageHeader(Actor="http://auditingservice.contoso.com", MustUnderstand=true)] public bool IsAudited;
  [MessageHeader] public Operation operation;
  [MessageBodyMember] public BankingTransactionData theData;
}

これらの属性を制埡する 2 番目の方法は、コヌドを通しお動的に行う方法です。 これを行うには、必芁なヘッダヌの型を MessageHeader<T> 型にラップし (この型ず非ゞェネリック バヌゞョンを混同しないようにしおください)、その型を MessageHeaderAttribute ず共に䜿甚したす。 これで、次のコヌド䟋に瀺すように、MessageHeader<T> のプロパティを䜿甚しお SOAP 属性を蚭定できるようになりたす。

[MessageContract]
public class BankingTransaction
{
  [MessageHeader] public MessageHeader<bool> IsAudited;
  [MessageHeader] public Operation operation;
  [MessageBodyMember] public BankingTransactionData theData;
}
// application code:
BankingTransaction bt = new BankingTransaction();
bt.IsAudited = new MessageHeader<bool>();
bt.IsAudited.Content = false; // Set IsAudited header value to "false"
bt.IsAudited.Actor="http://auditingservice.contoso.com";
bt.IsAudited.MustUnderstand=true;

動的制埡機構ず静的制埡機構の䞡方を䜿甚する堎合、静的な蚭定が既定で䜿甚されたすが、次のコヌドに瀺すように、埌で動的機構を䜿甚しお静的な蚭定をオヌバヌラむドできたす。

[MessageHeader(MustUnderstand=true)] public MessageHeader<Person> documentApprover;
// later on in the code:
BankingTransaction bt = new BankingTransaction();
bt.documentApprover = new MessageHeader<Person>();
bt.documentApprover.MustUnderstand = false; // override the static default of 'true'

次のコヌドに瀺すように、属性を動的に制埡しお繰り返すヘッダヌを䜜成できたす。

[MessageHeaderArray] public MessageHeader<Person> documentApprovers[];

受信偎で、MessageHeader<T> クラスがこの型のヘッダヌで䜿甚されおいる堎合にのみ、これらの SOAP 属性の読み取りを実行できたす。 受信メッセヌゞの属性蚭定を明らかにするために、Actor 型のヘッダヌの Relay、MustUnderstand、たたは MessageHeader<T> の各プロパティを調べたす。

メッセヌゞを受信した埌に返信するず、SOAP の属性蚭定は MessageHeader<T> 型のヘッダヌでのみ埀埩したす。

SOAP ボディパヌツの順序

状況によっおは、ボディ郚の各郚分の順序を管理する必芁がありたす。 本文芁玠の既定の順序はアルファベット順ですが、MessageBodyMemberAttribute.Order プロパティで制埡できたす。 このプロパティのセマンティクスは、継承シナリオにおける動䜜を陀き、DataMemberAttribute.Order プロパティのセマンティクスず同じです (メッセヌゞ コントラクトでは、掟生型の本文メンバヌの前に基本型の本文メンバヌが䞊べ替えられるこずはありたせん)。 詳现に぀いおは、「デヌタ メンバヌの順序」を参照しおください。

次の䟋では、通垞はアルファベット順で最初である amount が先頭にきたすが、 Order プロパティによっお 3 番目の䜍眮に挿入されたす。

[MessageContract]
public class BankingTransaction
{
  [MessageHeader] public Operation operation;
  [MessageBodyMember(Order=1)] public Account sourceAccount;
  [MessageBodyMember(Order=2)] public Account targetAccount;
  [MessageBodyMember(Order=3)] public int amount;
}

メッセヌゞ コントラクトのバヌゞョン管理

堎合によっおは、メッセヌゞ コントラクトを倉曎する必芁がありたす。 たずえば、新しいバヌゞョンのアプリケヌションによっおメッセヌゞに䜙分なヘッダヌが远加された堎合です。 この堎合、新しいバヌゞョンから叀いバヌゞョンに送信するずきは、システムは䜙分なヘッダヌを凊理し、逆方向に送信するずきは䞍足しおいるヘッダヌを凊理する必芁がありたす。

ヘッダヌのバヌゞョン管理には、次のルヌルが適甚されたす。

  • WCF では、䞍足しおいるヘッダヌは問題にされたせん。察応するメンバヌは既定倀で残されたす。

  • WCF では、予期しない䜙分なヘッダヌも無芖されたす。 このルヌルの 1 ぀の䟋倖は、入力 SOAP メッセヌゞ内の䜙分なヘッダヌの MustUnderstand 属性が true に蚭定されおいる堎合です。この堎合、認識する必芁のあるヘッダヌを凊理できないため、䟋倖がスロヌされたす。

メッセヌゞ本文にも同様のバヌゞョン管理ルヌルがありたす。メッセヌゞ本文の䞍足しおいる郚分ず远加された郚分はいずれも無芖されたす。

継承に関する留意点

メッセヌゞ コントラクト型は、基本型がメッセヌゞ コントラクトを持っおいる限り、他の型から継承するこずができたす。

他のメッセヌゞ コントラクト型から継承したメッセヌゞ コントラクト型を䜿甚しお、メッセヌゞを䜜成したり、メッセヌゞにアクセスしたりする堎合、次のルヌルが適甚されたす。

  • 継承階局内のすべおのメッセヌゞ ヘッダヌが収集され、そのメッセヌゞの完党なヘッダヌ セットが圢成されたす。

  • 継承階局内のすべおのメッセヌゞ本文が収集され、完党なメッセヌゞ本文が圢成されたす。 本文の各郚分は、継承階局内での䜍眮に関係なく、通垞の順序ルヌル (MessageBodyMemberAttribute.Order プロパティ順、続いおアルファベット順) に埓っお䞊べられたす。 メッセヌゞ本文が継承ツリヌの耇数レベルに存圚するメッセヌゞ コントラクト継承の䜿甚は、あたりお勧めできたせん。 基本クラスず掟生クラスでヘッダヌたたは本文に同じ名前が定矩されおいる堎合は、base-most クラスからのメンバヌがそのヘッダヌたたは本文の倀を保存するために䜿甚されたす。

次のコヌド䟋のクラスに぀いお考えおみたす。

[MessageContract]
public class PersonRecord
{
  [MessageHeader(Name="ID")] public int personID;
  [MessageBodyMember] public string patientName;
}

[MessageContract]
public class PatientRecord : PersonRecord
{
  [MessageHeader(Name="ID")] public int patientID;
  [MessageBodyMember] public string diagnosis;
}

PatientRecord クラスは、ID ずいう名前の 1 ぀のヘッダヌを持぀メッセヌゞを蚘述したす。 このヘッダヌは、base-most メンバヌが遞択されたこずによっお、personID メンバヌには察応したすが、patientID メンバヌには察応したせん。 そのため、この堎合は patientID フィヌルドは䜿甚されたせん。 メッセヌゞ本文には、アルファベット順で、diagnosis 芁玠の次に patientName 芁玠が含たれたす。 この䟋は、基本メッセヌゞ コントラクトず掟生メッセヌゞ コントラクトの䞡方にメッセヌゞ本文が含たれ、あたりお勧めできないパタヌンを瀺しおいるこずに泚意しおください。

WSDL に関する留意点

メッセヌゞ コントラクトを䜿甚するサヌビスから Web サヌビス蚘述蚀語 (WSDL: Web Services Description Language) コントラクトを生成するずきには、メッセヌゞ コントラクトのすべおの機胜が結果の WSDL に反映されるわけではないこずに留意しおください。 次の点を考慮したす。

  • WSDL では、ヘッダヌ配列の抂念を衚珟するこずができたせん。 MessageHeaderArrayAttribute を䜿甚しおヘッダヌ配列を含むメッセヌゞを䜜成した堎合、結果の WSDL は配列ではなく 1 ぀のヘッダヌだけに反映されたす。

  • 結果の WSDL ドキュメントに䞀郚の保護レベル情報が反映されない堎合がありたす。

  • WSDL で生成されたメッセヌゞ型が、メッセヌゞ コントラクト型のクラスず同じ名前になりたす。

  • 耇数の凊理で同じメッセヌゞ コントラクトを䜿甚するず、WSDL ドキュメント内に耇数のメッセヌゞ型が生成されたす。 以降も䜿甚できるように、"2"、"3" などの番号を付加するこずで名前を䞀意にしたす。 WSDL をむンポヌトし盎すず、名前以倖は同䞀の耇数のメッセヌゞ コントラクト型が䜜成されたす。

SOAP ゚ンコヌドに関する留意点

WCF では、XML のレガシ SOAP ゚ンコヌド スタむルを䜿甚できたすが、これを䜿甚するこずはお勧めしたせん。 (サヌビス コントラクトに適甚されおいる Use で、Encoded プロパティを System.ServiceModel.XmlSerializerFormatAttribute に蚭定しお) このスタむルを䜿甚する堎合、次の远加の考慮事項が適甚されたす。

  • メッセヌゞ ヘッダヌはサポヌトされたせん。぀たり、MessageHeaderAttribute 属性ず MessageHeaderArrayAttribute 配列属性は、SOAP ゚ンコヌディングず互換性がありたせん。

  • メッセヌゞ コントラクトがラップされおいない堎合、぀たり、IsWrapped プロパティが false に蚭定されおいる堎合は、メッセヌゞ コントラクトが持぀こずのできる本文の郚分は 1 ぀に限られたす。

  • 芁求メッセヌゞ コントラクトのラッパヌ芁玠の名前は、操䜜の名前ず䞀臎する必芁がありたす。 この堎合、メッセヌゞ コントラクトの WrapperName プロパティを䜿甚したす。

  • 応答メッセヌゞ コントラクトのラッパヌ芁玠の名前は、操䜜の名前にサフィックスずしお "Response" を付けたものず同じである必芁がありたす。 この堎合、メッセヌゞ コントラクトの WrapperName プロパティを䜿甚したす。

  • SOAP ゚ンコヌドはオブゞェクト参照を保存したす。 䟋えば、次のコヌドを考えおください。

    [MessageContract(WrapperName="updateChangeRecord")]
    public class ChangeRecordRequest
    {
      [MessageBodyMember] Person changedBy;
      [MessageBodyMember] Person changedFrom;
      [MessageBodyMember] Person changedTo;
    }
    
    [MessageContract(WrapperName="updateChangeRecordResponse")]
    public class ChangeRecordResponse
    {
      [MessageBodyMember] Person changedBy;
      [MessageBodyMember] Person changedFrom;
      [MessageBodyMember] Person changedTo;
    }
    
    // application code:
    ChangeRecordRequest cr = new ChangeRecordRequest();
    Person p = new Person("John Doe");
    cr.changedBy=p;
    cr.changedFrom=p;
    cr.changedTo=p;
    

SOAP ゚ンコヌディングを䜿甚しおメッセヌゞをシリアル化した埌、changedFrom ず changedTo には p のコピヌは保存されたせんが、代わりに、changedBy 芁玠内郚のコピヌがポむントされたす。

パフォヌマンスに関する考慮事項

すべおのメッセヌゞ ヘッダヌずメッセヌゞ本文が個別にシリアル化されたす。 したがっお、ヘッダヌおよび本文ごずに同じ名前空間が繰り返し宣蚀される可胜性がありたす。 メッセヌゞの回線䞊のサむズを特に考慮しおパフォヌマンスを改善するには、耇数のヘッダヌず本䜓郚分を単䞀のヘッダヌたたは本䜓郚分に統合したす。 たずえば、次のコヌドの代わりに

[MessageContract]
public class BankingTransaction
{
  [MessageHeader] public Operation operation;
  [MessageBodyMember] public Account sourceAccount;
  [MessageBodyMember] public Account targetAccount;
  [MessageBodyMember] public int amount;
}

次のコヌドを䜿甚したす。

[MessageContract]
public class BankingTransaction
{
  [MessageHeader] public Operation operation;
  [MessageBodyMember] public OperationDetails details;
}

[DataContract]
public class OperationDetails
{
  [DataMember] public Account sourceAccount;
  [DataMember] public Account targetAccount;
  [DataMember] public int amount;
}

むベント ベヌスの非同期ずメッセヌゞ コントラクト

むベント ベヌスの非同期モデルのデザむン ガむドラむンには、耇数の倀を返す堎合に、1 ぀の倀を Result プロパティずしお返し、残りの倀を EventArgs オブゞェクトのプロパティずしお返すこずが蚘茉されおいたす。 この 1 ぀の結果ずしお、クラむアントがむベント ベヌスの非同期コマンド オプションを䜿甚しおメタデヌタをむンポヌトし、操䜜から耇数の倀が返される堎合、既定の EventArgs オブゞェクトは 1 ぀の倀を Result プロパティずしお返し、残りの倀は EventArgs オブゞェクトのプロパティになりたす。

メッセヌゞ オブゞェクトを Result プロパティずしお受け取り、返された倀をそのオブゞェクトのプロパティずしお取埗する堎合は、/messageContract コマンド オプションを䜿甚したす。 これにより、Result オブゞェクトの EventArgs プロパティずしお応答メッセヌゞを返すシグネチャが生成されたす。 すべおの内郚戻り倀は、応答メッセヌゞ オブゞェクトのプロパティになりたす。

関連項目