自分が思いっきりどはまったので手順のメモとして。
まず、サーバー側に適当にサービスを作成しておきます。
ここでは、仮に「MyWcfService.svc」という名前でsvcファイルを作成して、サービスのエントリーポイントとしておきます。
次に、クライアントで、このサービスに対してサービス参照を追加します。
とりあえず、MyWcfService.svcファイルをブラウザで表示して、表示されたURL(例えば、http://localhost:10000/MyWcfService.svc)を
コピーってサービス参照の追加の画面でURLとして指定しましょう。
Client側のプロジェクトには、「ServiceReference1」なんてのが追加されてるはずなので、
ServiceReference1.MyWcfServiceClient client = new ServiceReference1.MyWcfServiceClient();
try
{
client.Execute();
}
finally
{
client.Close();
}
といった感じでアクセスできるはずです。
では、以下のコードで、ExecuteメソッドとPostExecuteメソッド間におけるクッキーの受け渡しを考えると・・・。
ServiceReference1.MyWcfServiceClient client1 = new ServiceReference1.MyWcfServiceClient();
try
{
client1.Execute();
}
finally
{
client1.Close();
}
ServiceReference1.MyWcfServiceClient client2 = new ServiceReference1.MyWcfServiceClient();
try
{
client2.PostExecute();
}
finally
{
client2.Close();
}
さて、どうやりましょう。
単純には、app.configファイルにあるWCFの構成設定を変更して、
<system.servicemodel>
<bindings>
<basichttpbinding>
<binding allowcookies="true" name="NewBinding" />
</basichttpbinding>
</bindings>
<client>
<endpoint mywcfservice.svc?? localhost:10000 http: address=">
binding="basicHttpBinding" bindingConfiguration="NewBinding"
contract="ServiceReference1.MyWcfService"
name="BasicHttpBinding_MyWcfService" />
</client>
</system.servicemodel>
としたいところです。
が、これだとNGです。
ServiceReference1.MyWcfServiceClientクラスを生成する場合、これは内部的にはChannelFactoryクラスが利用されていますが、
ChannelFactoryクラスのCookieのスコープはインスタンスごとに異なります。
このため、単純に構成ファイルにCookieを使うという宣言をしただけでは2つ目のサンプルコードでCookieを受け渡すことはできません。
そこで、さっきのサンプルを以下のように変更します。
CookieContainer container = new CookieContainer();
ServiceReference1.MyWcfServiceClient client1 = new ServiceReference1.MyWcfServiceClient();
try
{
using (OperationContextScope scope = new OperationContextScope(client1.InnerChannel))
{
client1.Execute();
//ブログの横幅の都合でいろいろ取得しながら書いてます。
MessageProperties properties = OperationContext.Current.IncomingMessageProperties;
HttpResponseMessageProperty httpResponse;
httpResponse = properties[HttpResponseMessageProperty.Name] as HttpResponseMessageProperty;
string cookie = httpResponse.Headers[HttpResponseHeader.SetCookie];
container.SetCookies(new Uri(“http://dummy/”), cookie);
}
}
finally
{
client1.Close();
}
ServiceReference1.MyWcfServiceClient client2 = new ServiceReference1.MyWcfServiceClient();
try
{
using (OperationContextScope scope = new OperationContextScope(client2.InnerChannel))
{
MessageProperties properties = OperationContext.Current.OutgoingMessageProperties;
HttpRequestMessageProperty httpRequest;
if (properties.ContainsKey(HttpRequestMessageProperty.Name))
{
httpRequest = properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
}
if (httpRequest == null)
{
httpRequest = new HttpRequestMessageProperty();
properties.Add(HttpRequestMessageProperty.Name, httpRequest);
}
httpRequest.Headers.Add(HttpRequestHeader.Cookie, container.GetCookieHeader(new Uri(“http://dummy/”)));
client2.PostExecute();
}
}
finally
{
client2.Close();
}
最後に、設定ファイルでallowCookies = “true”としている場合には、”false”に設定しなおします。
# trueにしているとWCFランタイム内で、Cookieの再設定が行われ、セットしていたものが無効になってしまうようです
これで、無事に完成です。
たとえば、認証処理とからめて利用するような場合には、重要ですね。