今天,茄子_2008反饋他部落格中的“C++”標籤失效。檢查了一下代碼,產生連結時用的是HttpUtility.UrlEncode(url),從連結地址擷取標籤時用的是HttpUtility.UrlDecode(url),從Encode到Decode,“C++”變成了“C ”(加號變成空格)。這是大家熟知的問題,這裡我們分析一下這個問題,並給出解決方案。
先看一下問題發生的過程:
1. 原始連結:
http://www.cnblogs.com/xd502djj/tag/C++/
2. HttpUtility.UrlEncode之後,得到:
http://www.cnblogs.com/xd502djj/tag/C%2b%2b/
3. Request.RawUrl,得到:
http://www.cnblogs.com/xd502djj/tag/C++/
4. HttpUtility.UrlDecode,得到:
http://www.cnblogs.com/xd502djj/tag/C /
上面第3步已經得到正確的結果,第4步的UrlDecode反而將加號變為了空格。
看來解決方案很簡單,取消多此一舉的UrlDecode,開始我們也是這麼乾的。過了一段時間,有使用者反映“Windows Phone”的標籤失效了,變成了“Windows+Phone”。我們一查,原來是在HttpUtility.UrlEncode時,空格被轉換為加號,需要調用UrlDecode將加號還原為空白格,於是又把HttpUtility.UrlDecode加上(忘了之前的“C++”標籤問題)。然後,“C++”標籤又失效...這樣反反覆複,看似Bug很多,工作很忙,實際上就是一個Bug...
終於有一天,我們說“再也不能這樣過”,開始尋找解決方案:
既然HttpUtility.UrlEncode()不能用,那在.NET中找找有沒有替代品。
先找到了HttpUtility.UrlPathEncode()。嘿,有用,輕鬆搞定“C++”與空格問題,但是...後來發現搞不定“C#”,它沒有對“#”進行編碼。
繼續尋找...找到了Uri.EscapeUriString(),與HttpUtility.UrlPathEncode()同樣的問題。
繼續尋找...終於找到了...Uri.EscapeDataString(),搞定!請看下面的測試代碼:
public void UrlEncodeTest()
{
string url = "C++ C#";
Console.WriteLine(HttpUtility.UrlEncode(url));//C%2b%2b+C%23
Console.WriteLine(HttpUtility.UrlPathEncode(url));//C++%20C#
Console.WriteLine(Uri.EscapeUriString(url));//C++%20C#
Console.WriteLine(Uri.EscapeDataString(url));//C%2B%2B%20C%23
}
註:運行環境.NET4。