HttpUtility.ParseQueryString與雙頻式Request參數解析

手邊有個需求,要把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

【延伸閱讀】

歡迎推文分享:
Published 06 January 2010 06:23 PM 由 Jeffrey
Filed under: ,
Views: 13,078



意見

# Ark said on 06 January, 2010 08:33 AM

Regex.IsMatch(Request.RawUrl,

//利用以下特徵簡易識別出BIG5 UrlEncode

"%[a-f][0-9a-f]%", RegexOptions.IgnoreCase)

<==請教出處?

另求gb2312

# Jeffrey said on 06 January, 2010 03:38 PM

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

# ALEX said on 20 May, 2010 11:32 PM

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

# evan said on 11 April, 2013 02:52 AM

剛好需要,太感謝了!

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<January 2010>
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456
 
RSS
創用 CC 授權條款
【廣告】
twMVC
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication