次の2つのURLを見てみましょう。同じパラメータを通していますか? aaa.aspx?tag=.net%bc%bc%ca%f5 aaa.aspx?tag=.net%e6%8a%80%e6%9c%af
違うように見えますが、実際にはすべて「.net技術」としてUrlEncodeを使っています。ただし、1つはGB2312エンコーディング、もう1つはUtf-8エンコーディングです。 以下のコードは上記の符号化効果を得ることができます:
string tmp1 = System.Web.HttpUtility.UrlEncode(".net technology", System.Text.Encoding.GetEncoding("GB2312")); string tmp2 = System.Web.HttpUtility.UrlEncode(".net technology", System.Text.Encoding.UTF8);
当社のウェブページは他のプログラムから呼び出されることがあります。 例えば、オペレーティングシステムのASPページは中国語簡体化で、ASP.net ページに中国語パラメータを渡す必要があります。 デフォルトでは、中国簡体字OSでは、ASPのServer.UrlEncodeメソッドが中国語をGB2312エンコーディングでエンコードします。 しかしデフォルトでは、ASP.net ページはUTF-8でエンコードされています。 この場合、Request.QueryString["Tag"]を使って値を受け入れると、中国語の情報は受け入れられず、ステップバイステップのデバッグで文字が乱れているのが見えます。 現時点では、Request.QueryString["Tag"]は文字が乱れていても受け入れられますが、URL自体は乱れていません。
解決策は、URL内のパラメータを自分で解析し、デフォルトのUTF-8エンコーディングではなくGB2312のエンコーディングに従ってパラメータの値を復号することです。 実際、Microsoftも対応する関数を提供しているため、私たち自身で正則表現を使ってURL文字列を解析する必要はありません。
デモコードは以下の通りです:
string q = Request.Url.Query;
System.Collections.Specialized.NameValueCollection nv = System.Web.HttpUtility.ParseQueryString(q, System.Text.Encoding.GetEncoding("GB2312")); Response.Write(nv["Tag"]);
Lutz Roederの.NET Reflectorを使ってSystem.Web.HttpUtility.ParseQueryStringメソッドの実装を見てみましょう。 繰り返し確認すると、URLパラメータ文字列解析を最終的に扱うコードは以下の通りです。
System.Web.HttpValueCollectionクラスの以下の関数はURLパラメータの解析を実装しています ここでは、各キャラクターが分析を行うことがわかります。
- internal void FillFromString(string s, bool urlencoded, Encoding encoding)
- {
- int num1 = (s != null) ? s.Length : 0;
- for (int num2 = 0; num2 < num1; num2++)
- {
- int num3 = num2;
- int num4 = -1;
- while (num2 < num1)
- {
- switch (s[num2])
- {
- case ’=’:
- if (num4 < 0)
- {
- num4 = num2;
- }
- break;
- }
- num2++;
- }
- string text1 = null;
- string text2 = null;
- if (num4 >= 0)
- {
- text1 = s.Substring(num3, num4 - num3);
- text2 = s.Substring(num4 + 1, (num2 - num4) - 1);
- }
- else
- {
- text2 = s.Substring(num3, num2 - num3);
- }
- if (urlencoded)
- {
- base.Add(HttpUtility.UrlDecode(text1, encoding), HttpUtility.UrlDecode(text2, encoding));
- }
- else
- {
- base.Add(text1, text2);
- }
- if ((num2 == (num1 - 1)) && (s[num2] == ’&’))
- {
- base.Add(null, string.Empty);
- }
- }
- }
コードをコピーします
相手が私たちに渡すエンコーディング方法については、パラメータとして渡すのが最善であり、ユーザーのパラメータに従って復号できるからです。 |