<   2008年 06月 ( 1 )   > この月の画像一覧

[C#][JavaScript] Cookie の操作

Cookie 関連ですごくハマったので、メモしておく。

普段は「贈らない・求めない・受け取らない」ようにしているので
(うつくしい選挙って感じw)、
Cookie のことは深く考えたことがなかったのね。
とりあえず拒否! だから(笑)

ちなみに、環境はサーバもクライアントも同一マシン上。
  WindowsXP
  VisualStudio 2003
  IIS v5.1
  ASP.NET 2.0.50727
  IE6 sp2

何がしたかったのか


まず、何がしたかったのかというと。
ASP.NET で、サーバ側 C#、クライアント側 JavaScript を使い
数回ポストバックしながら、C# と JavaScript で値をやり取りしたかったわけ。
ActiveX の関数の戻り値を見て、C# で動作を変更したかった。
例えばこんな感じ。

  サーバ側 C# methodA 実行
  ↓
  クライアント側 JavaScript ActiveX functionB 実行
  ↓ ポストバック
  サーバ側 C# method methodC 実行
  ↓
  クライアント側 JavaScript ActiveX functionD 実行
  ↓ ポストバック
  サーバ側 C# 他画面へ遷移

サーバ側 C# とクライアント側 JavaScript の値のやり取りには
Cookie を使用。
C# のみなら Session オブジェクトを使えるのだけど、
JavaScript だからそうもいかず。
HTML の form 要素内に hidden を作成して、
値をやり取りするという方法もあるけど、
ちょっと人にはお見せしたくないデータなので、
hidden だと「ソースを表示」で見えちゃうから、よろしくないと言われた。
なわけで、Cookie を使うことにしたのだが。

C# で Cookie を作成/上書き


C# では、Cookie と名のつくものは2種類参照できる。
クライアントからサーバに送られた Request.Cookies と
サーバからクライアントに送られた Response.Cookies
(字面が似てて読みづらいので、クライアントから見た動作で、
 前者を要求、後者を応答と書くことにする)。
関数の実行結果のステータスを Cookie で判断するので、
Cookie に値の設定、書き換え、削除が必要になる。
Cookie に値を設定するときはこのように。
前者の方法では、キーである LARGE が既存なら上書き、ないなら新規設定になる。
後者の方法は、新規作成しか試してないので、上書きできるか不明。
HttpCookie aCookie = new HttpCookie("LARGE");
aCookie.Values["SMALL1"] = "val1";
aCookie.Values["SMALL2"] = "val2";
Response.Cookies.Add(aCookie);
// ↑このやり方が一般的
// ↓このやり方はあんまり一般的じゃないっぽい
HttpCookie hc = new HttpCookie("LARGE", "SMALL1");
Response.AppendCookie(hc);

これで、サーバ側で作られた Cookie がクライアントに送られる(応答)。

JavaScript で Cookie を作成/上書き/削除


これをクライアント側 JavaScript で読みだすと、こうなる。
document.write(document.cookie);
 → LARGE=SMALL1=val1&SMALL2=val2

お分かりの通り、キーが入れ子になっている状態。
JavaScript で個々の値を取得したいときは、ちゃんとパージングしないとね。
この状態で、JavaScript で値を設定するには、こんな風に。
/* MIDDLE というキーが追加される */
document.cookie = "MIDDLE=A1=V1&A2=V2";
/* LARGE は既存なので、上書きされる */
document.cookie = "LARGE=A3=V3&A4=V4";

注意点は、既存かどうかで、追加か上書きか、動作が違うこと。
確実に既存の Cookie に上書きしたいなら、
いっぺん削除した方が良いと思う。
削除の仕方はこんな風。
dt = new Date();
dt.setYear(dt.getYear() - 1);
document.cookie = "LARGE=;expires=" + dt.toGMTString();

注意点は、削除メソッドはなくて、
期限を過去にすることで、Cookie を期限切れにすること。
そして、実はこれを行った直後は Cookie は削除されない。
というのは、Cookie が削除されるタイミングはブラウザ依存らしいから。
動作的には、Cookie の送受信が行われる時に削除されるっぽい印象。
そして更に、これを行っても、サーバ側にある Cookie は削除されない。
というのは、これは、クライアントからサーバに送られる
要求側の Cookie の設定だから。

戻って C# で Cookie を削除


サーバに残っている Cookie も削除しなくてはいけないかも。
クライアントで古い Cookie を削除したのに、
また古い Cookie が送られて来てしまうから。
サーバからクライアントに送られる応答側の Cookie を削除するには、
サーバ側の C# で処理しなくてはいけない。
これも同様に、削除できないので、有効期限切れにする。
参考:ASP.NET 方法 : Cookie を削除する
if(Request.Cookies["LARGE"] != null) {
  HttpCookie hc = new HttpCookie("LARGE");
  hc.Expires = DateTime.Now.AddDays(-1d);
  Response.Cookies.Add(hc);
}

これで、サーバからクライアントに送られるはずの応答の Cookie も
期限切れのために送られない。
削除(の気分)なのに、設定/上書きと同じ Add メソッドを使うのが面白い。

ちなみに、Request.Cookies は
ブラウザから送られてきた要求側の Cookie なので、
基本的に変更不可になっているようだ。
IIS 7.0 の統合モードなら変更できるらしいけど、
普通の開発ではあんまりいじる必要もないんじゃないかと思う。

おすすめツール


IE で Cookie を見るときは、MS 純正の
  IE Developer Toolbar
が便利だった。
プラグインはたくさんあるけれど、純正というのが安心だし。

FireFox で HTTP ヘッダに入っている Cookie の様子を見るには、
  View Cookies
  Live HTTP headers
が便利。

思ったこと


JavaScript の方は、document.cookie 入っているのが応答でもあり要求でもあり、
インタフェースが1つでわかりやすいんだけど、
C# は要求と応答の Cookie があるので、
「あれ?今どっから来てどこに行くんだっけ?」となりがち。
しかも Request と Response と、字面も似てるし(>_<)
何度もぐるぐるポストバックするようなのを真面目に書くときは、
シーケンス図を書いて整理するのがいいかも。

で、大事だなーと思ったのは以下の2点。
・Cookie はサーバにもクライアント(ブラウザ)にも保存されている
・Cookie が削除される(期限切れになる)のは、(多分)送受信時
 それまでは削除されない

あ、あと注意。
Session を使っているなら、
Response.Cookies.Remove();

は使わない方がいい。
SessionID は Cookie に保存されているのだが、
それもまるっと削除しちゃうので、セッション切れになっちゃうよ。

しかし、こういうソースって、エキブロで投稿するのは面倒臭い。
JavaScript 不可なんで、怒られるのね(^^;;
[PR]
by xiaoxia | 2008-06-03 18:20 | プログラム言語 | Comments(0)

ダメ女プログラマ&主婦&腐女子&バイオリン弾き


by 小霞