2

私の WCF サービスは、サービスへの共通のエントリ ポイントを表すために、キャッチオール アクションと応答アクションでマークされた単一の操作をエクスポートします。

[ServiceContract]
public interface IService
{
    [OperationContract (Action="*", ReplyAction="*")]
    Message MyMethod (Message msg);
}

クライアント プロキシは引き続きデータコントラクトとして生成されます。

しかし、私が見つけたのは、クライアントがデータ コントラクトを送信しているにもかかわらず、シリアル化されている場合、本体はデータ コントラクト自体ではなく、データ コントラクトとmsg同等のメッセージコントラクトのように見えるということです。

内部のデータ コントラクトを抽出するには、受信した XML を手動で解析する必要があることを除けば、これでも問題ありません。サービス自体には使用する実際のMessageContract型がないため、本体にアクセスすることは、ノードの抽出、要素の再ラベル付けなどを意味します。これは、公開された操作がMessageベースではない場合に、おそらく WCF が隠れて処理しているものの手動プロセスです。

データ コントラクト間のデータ コントラクトの場合、WCF はどのようにこれを行うのですか? 同じプロセスを使用できる方法はありますか?

4

2 に答える 2

2

これが正しいデフォルトの動作です。リクエストまたはレスポンス データが送信されるたびに、ラッピング要素で自動的にラップされます。これは、ラップされたパラメータ スタイルとも呼ばれます。それを使用せず、代わりに Bare パラメーター スタイルを使用する場合は、メッセージ コントラクトを定義し、その IsWrapped プロパティを false に設定する必要があります。この簡単な例のように:

[ServiceContract]
public interface IService
{
    [OperationContract]
    GetMessageResponse GetMessage(GetMessageRequest request);
}

[MessageContract(IsWrapped = false)]
public class GetMessageResponse
{
    [MessageBodyMember]
    public string Result { get; set; }
}

[MessageContract(IsWrapped = false)]
public class GetMessageRequest
{
    [MessageBodyMember]
    public string Data { get; set; }
}

GetMessage 操作は、リクエストとレスポンスでラッピングを使用しません。

制限は、操作がパラメーターとして単一の MessageContract のみを受け入れる必要があり、常に MessageContract を返す必要があることです (void を返す場合でも)。したがって、要件を達成する最も簡単な方法は、属性を置き換えて、すべてのデータ コントラクトをメッセージ コントラクトに変換することです。

もう 1 つの方法は、要求と応答ごとに個別のメッセージ コントラクトを作成し、データ コントラクト型のプロパティをメッセージ本文として使用することです。何らかの理由で、操作ごとに 2 つの追加のメッセージ コントラクトを作成するという考えが気に入らず、古いデータ コントラクトを保持したい場合は、少しハックを使用できます (これを使用する理由はわかりませんが、機能します)。データ コントラクトに MessageContract 属性を追加し、すべてのデータ メンバーに MessageBodyMember 属性を追加します。

[DataContract, MessageContract(IsWrapped = false)]
public class MyData
{ 
    [DataMember, MessageBodyMember]
    public string Data { get; set; }
}
于 2010-08-27T23:29:54.010 に答える
0

あなたが見ているのは正しい動作であるというLadislavに同意します。MSDN には、WCF がメッセージを送受信するときに何が起こっているかを説明する優れたドキュメントがあります。

http://msdn.microsoft.com/en-us/library/aa347789.aspx

あなたが求めているものに関連する重要な段落は次のとおりです。

メッセージの読み取りは、メッセージの受信時にサービス フレームワークによって主に使用されます。たとえば、DataContractSerializer が使用されている場合、サービス フレームワークは本文を介して XML リーダーを取得し、それをデシリアライゼーション エンジンに渡します。デシリアライゼーション エンジンは、メッセージの要素ごとの読み取りと、対応するオブジェクト グラフの構築を開始します。

そのため、フレームワークは を使用しDataContractSerializerて、ペイロード (XML 情報セット) を受信時に適切なクラスに逆シリアル化します。ペイロードを抽出し (おそらくMessage.GetReaderAtBodyContents()XmlReader を返すものを使用)、次に DataContractSerializer を使用して、返されXmlReaderた .

うまくいけば、これが役に立ちます!

于 2010-08-28T00:03:07.697 に答える