以前、WCF でクライアントからサービスにメタ情報を渡す方法として、コンテキスト付きバインディングを使う方法を紹介しました。
クライアントが Windows アプリケーションなら、この方法で良いんですが、Silverlight の場合使えません。Silverlight にはコンテキスト付きバインディングが無いんです。まぁ、コンテキスト付きバインディング自体、WF から拝借してきたものなので、以前から気持ち悪さを感じていたんですが…。
そもそも、コンテキスト付きバインディングなんか使わずに、直接メッセージヘッダにデータを突っ込めば良かったんです。こんな風に。
// チャネル作成 IFooService client = ChannelFactory<IFooService>.CreateChannel( new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/Foo")); // ヘッダ操作は OperationContextScope 内で行う using (OperationContextScope scope = new OperationContextScope((IClientChannel)client)) { // ヘッダに格納して送る情報 User user = new User { Name = "ルフィ" }; // ヘッダを追加 MessageHeader header = MessageHeader.CreateHeader( "User", "UserHeader", user); OperationContext.Current.OutgoingMessageHeaders.Add(header); // サービス呼び出し client.Foo(); } // チャネルを閉じる ((IClientChannel)client).Close();
サービス側では、こんな風にヘッダからデータを取り出せます。
public class FooService : IFooService { public void Foo() { // ヘッダからデータを取り出す // name と namespace を指定する var user = OperationContext.Current.IncomingMessageHeaders .GetHeader<User>("User", "UserHeader"); Console.WriteLine(user.Name); } }
OperationContext には OutgoingMessageHeaders と IncommingMessageHeaders の2つのプロパティがあって、ちょっとややこしいです。私は次のように整理しています。
- OutgoingMessageHeaders は、「出ていくメッセージ」のヘッダを操作するためのプロパティ。
- メッセージを送る側が使う。
- IncommingMessageHeaders は「入ってきたメッセージ」のヘッダを操作するためのプロパティ。
- メッセージの受ける側が使う。
「そのまんま」とか言わないw。