[C#][javascript] C# と javascript でつまった

最近、C# とか javascript とかで、ASP.NET をやっている。
当然、ヴィジュアル・スタディオ(笑)を使っている。
初めてやったから、まずプロジェクトってファイルを作るところまでに数日(^^;;
C# も初めてなので、HTML 側と C# 側のつながりを理解するのに、さらに数日。
気分はスクリプトな web アプリなのに、
「ビルド」とかって正直なじめないしー(((^^;;
まぁ C# 使うんだから仕方ないわな。

で、つまづいたことと、解決した方法。
もっと良い方法があったら、ご教示くださいませ。

C# と javascript で値を受け渡す方法



☆C# から javascript
//C# で設定
msg.Text = "poipoi";
---------------------------
<!-- HTML の内容 -->
<asp:HiddenField ID="msg" runat="server" />
---------------------------
/* javascript で読み出し */
var msg = document.all["msg"].value;


☆javascript から C#
//先に javascript で設定して postback してから C# で読み出し
if(IsPostBack == true) {
// postback 時に読み出し
string msgstr = msg.Text;
}
--------------------------------------------------
<!-- HTML の内容-->
<form id="foo" runat="server">
<asp:HiddenField ID="msg" runat="server" />
</form>
--------------------------------------------------
/* javascript で設定してsubmit */
foo.msg.innerHTML = "文字列";
foo.submit();

この場合、javascript はクライアント側で動くので、
そのあとにサーバ側の C# に戻さなくちゃならない。
流れとしては、C#(スルー)->javascript(設定)->C#(読み出し)になる。

hidden に設定してしまうと、ソース表示で値が見えてしまう。
見えてしまうのがイヤな場合は、Cookie に設定するしかないのかな。
Session じゃ、JavaScript では操作できないからな。

C# とjavascript の encode/decode


C# と javascript で、URL エンコード/デコードする関数と
UTF-8 の文字列を入力にしたときの結果はこんな感じ。

C#:
HttpUtility.UrlEncode(str) -> %aa%bb%cc
逆は HttpUtility.UrlDecode

javascript:
escape(str) -> %u1111%u2222
逆は unescape

C# の方は UTF-8 の文字を 1 バイトずつエンコードするが、
javascript の方は、UTF-16(UCS-2?UCS-4?) を 1 文字ずつエンコードする。
デコード関数は、エンコードした文字列をデコードするので、
エンコード関数の結果が違うと、デコードできないわけで、
このままだと C# と javascript では相互にエンコード/デコードできない。
たとえば、C# で cookie を設定して、
javascript でデコードするような時は、
UTF-16 なバイト列を 2 バイトずつエンコードして
cookie に設定しなくてはならない。
ちなみに、エンディアンも関係あるので、
そこも考慮しなくちゃならないっぽい。
javascript 側でやってもいいんだけど、
多分、C# の方がクラスが充実していて楽だと思う。

試行錯誤の結果がこれ。
すごくカコワルイ。
C# じゃないじゃん、これ(笑)
もっとスマートなやり方があると思うので、
ぜひ教えてください。
// C# でエンコード
string v = "cookieに格納したいマルチバイト文字列";
byte[] b_arr = Encoding.Unicode.GetBytes(v);
string result ="";
// 2バイトずつ読み込んで %u**** というセットを作る
// 前後を逆にしているのはサーバが Intel 機だから
for (int i=0; i<b_arr.Length; i=i+2) {
   result += String.Format("%u{0,0:X2}{1,0:X2}",
               (int)b_arr[i+1], (int)b_arr[i]);
}
HttpCookie mycky = new HttpCookie("mykey", res);
HttpContext.Current.Response.AppendCookie(mycky);
--------------------------------------------------------
/* JavaScript でデコード */
unescape(document.cookie);

C# の文字列は、文字列として出力させてみると UTF-8 なんだけど、
Windows の内部的には UCS-2(UCS-4?) で持っているので、
文字コード変換しなくて良いらしいよ。
ファイル出力も stream の文字コードを設定すると、自動変換するらしい。
なるほど java ぽいわ、って感じ。

追記(2008/08/16):
javascript に encodeURIComponent / decodeURIComponent という
関数があるのを、コメントで教えていただいた。
実行してみた結果はこんな感じ。
/* 全半角混じりの文字列をエンコードしてみる */
escape("Aあ亜&(+_-)")
  -> %u3042%u4E9C%26%28+_-%29
encodeURIComponent("Aあ亜&(+_-)")
  -> %E3%81%82%E4%BA%9C%26(%2B_-)

/* 上記のエンコード結果をデコードしてみる(できて当然だけど) */
decodeURIComponent("%E3%81%82%E4%BA%9C%26(%2B_-)")
  -> あ亜&(+_-)

encodeURIComponent を使うと、漢字も+も1バイトずつエンコードさるし、
デコードもできるっぽい。
なので、上記の自作関数を使って %u**** を作らなくても、
  C# : HttpUtility.UrlEncode -> javascript : decodeURIComponent
という組み合わせなら、無事に動きそう。
まだ試してないけど。
でも、半角ハイフンやアンスコやカッコをエンコードしたい時はどうするのだろう。
RFC 的にしなくていいから、しなくていいの?
[PR]
Commented by himajin100000 at 2008-06-13 14:56 x
久しぶりに読んでみた・・・けど,「encodeURIComponent関数」ではなく「escape関数」を使った理由はあるのだろうか?

#2008-05-19なので時期逃している印象あるけど
メモ:
ttp://blogs.msdn.com/yangxind/archive/2006/11/09/don-t-use-net-system-uri-unescapedatastring-in-url-decoding.aspx
Commented by himajin100000 at 2008-06-13 14:59 x
#URIを含めたのでスパム扱いされたのでh抜いてます(原因調査に2コメント。つまりこの記事のコメントは全て俺)
Commented by xiaoxia at 2008-06-15 14:26
●himajinさま
encodeURIComponent関数というのは、JavaScriptの方でしょうか。そんな関数があることを初めて知りました(^^;;
C#でエンコードしてJavaScriptで読み出すので、使うとすれば、対応するdecodeURIComponent関数を使う事になるかと思います。関数の動作などは試してみないとわからないので、試してみてから、もっと良い方法があったら、記事に追記しようと思います。
ちなみに、このエスケープ処理は、Cookieに設定する文字列なので、+や_なども、すべてエスケープしなくてはならない、というポリシーです。
by xiaoxia | 2008-05-19 22:17 | プログラム言語 | Comments(3)

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


by 小霞