手邊有個需求,要把IIS Log Query String裡的參數解析出來,例如: "?a=LeftMenu&t=%u9ed1%u6697%u57f7%u884c%u7dd2&u=/Darkthread.aspx&_=1262748681109"。需求不難,但要拆解參數、UrlDecode,眉角還挺多的。原本已捲起袖子打算自己動手寫,頓時想到佛心的HttpUtility Class可能會內建,一找之下,果然發現了好東西HttpUtility.ParseQueryString!

送字串進去就傳回NameValueCollection,連%u9ed1這些Uncode編碼也會一併解好,十分方便。

static void Main(string[] args)
{
    string query = 
"?a=LeftMenu&t=%u9ed1%u6697%u57f7%u884c%u7dd2&u=/Darkthread.aspx&_=1262748681109";
    NameValueCollection nvc =
        HttpUtility.ParseQueryString(query);
    foreach (string key in nvc.Keys)
    {
        Console.WriteLine("{0} => {1}", key, nvc[key]);
    }
    Console.Read();
}

執行結果:

a => LeftMenu
t => 黑暗執行緒
u => /Darkthread.aspx
_ => 1262748681109

看到這個方法,我想到前陣子網友三腳貓提了一個ASP串接ASP.NET的URL編碼問題,於是幫它想出一個新用途。我們都知道Query String編碼時有Encoding之分,例如: 黑暗執行緒用Big5編碼做UrlEncode會變成%b6%c2%b7t%b0%f5%a6%e6%ba%fc,此時用ASP.NET Request預設編碼(UTF-8)解析就會產生亂碼。

雖然我們可以修改ASP.NET Request的Encoding設定或ASP檔的Encoding設定,若產生URL的一方無法配合更改,而我們又不想為了部分Request更動整個ASP.NET Request的編碼設定,我想到可以搞出類似以下的做法,不管傳入Unicode或BIG5版的UrlEncode,都可以正確解析:

<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
    string paramS = null;
    if (Request.Url.Query.Length > 0 &&
        Regex.IsMatch(
            Request.RawUrl,
            //利用以下特徵簡略(但草率)識別出BIG5 UrlEncode
            "%[a-f][0-9a-f]", RegexOptions.IgnoreCase)
        )
    {
        NameValueCollection nvc =
            HttpUtility.ParseQueryString(
            Request.RawUrl.Substring(Request.RawUrl.IndexOf("?") + 1),
            Encoding.GetEncoding(950));
        paramS = nvc["s"];
    }
    else
        paramS = Request["s"];
    Response.Write("s=" + paramS);
    Response.End();
}
</script>

測試以下兩種URL,都可以正確解出"黑暗執行緒",不知道這樣可不可以稱為"支援雙頻"? 呵呵呵...

  • Default.aspx?s=%u9ed1%u6697%u57f7%u884c%u7dd2
  • Default.aspx?s=%b6%c2%b7t%b0%f5%a6%e6%ba%fc

【延伸閱讀】


Comments

# by Ark

Regex.IsMatch(Request.RawUrl, //利用以下特徵簡易識別出BIG5 UrlEncode "%[a-f][0-9a-f]%", RegexOptions.IgnoreCase) <==請教出處? 另求gb2312

# by Jeffrey

to Ark, 我校正了一下文字"//利用以下特徵簡略(但草率)識別出BIG5 UrlEncode"以免誤會,這個判別方法很不精準,原則上是抓BIG5的漢字範圍是從0xA440-0xC67E(REF: http://zh.wikipedia.org/wiki/%E5%A4%A7%E4%BA%94%E7%A2%BC),而假設一般的URL Encode中是不會用到%a0以上的字元,所以用這個粗略的方法,看到黑影就開槍。不過,其他如UTF-8、GB2312等透過UrlEncode也會產生類似特徵,要做到不同編碼自動識別,複雜度變高許多,就不是我這段輕鬆小品型程式碼可以涵蓋的了。

# by ALEX

請問若是使用VB的話,該如何改寫呢?

# by evan

剛好需要,太感謝了!

Post a comment