通過前面兩篇《Request 接收參數亂碼原理解析一:服務器端解碼原理》和《Request 接收參數亂碼原理解析二:瀏覽器端編碼原理》,了解了服務器和瀏覽器編碼解碼的原理,接下來結合項目中遇到的具體問題,分析亂碼問題的解決方法。
1.用戶身份驗證Cookie亂碼問題
用戶登錄后,通常用Cookie記錄身份,如把用戶名記錄到Cookie中,其它頁面讀取Cookie,對Cookie值驗證,符合一定規則的話則認為是合法用戶。

protected void Page_Load(object sender, EventArgs e) { //假定登陸用戶名為北京(歷史原因系統允許有中文名) Response.Cookies["username"].Value = Server.UrlEncode("北京"); }

protected void Page_Load(object sender, EventArgs e) { //讀取Cookie,如果用戶名存在則認為登陸成功(實際驗證比這要復雜很多) string userName = Server.UrlDecode(Request.Cookies["username"].Value); bool isLogin = userName == "北京"; Response.Write("用戶" + userName + "登陸" + (isLogin ? "成功" : "失敗")); }
因為用戶名存在中文問題,寫入編碼和讀取解碼都是在服務器端進行的,所以寫Cookie時將值用Server.UrlEncode()編碼,讀取Cookie值時用Server.UrlDecode()解碼,通常認為這兩個函數是成對出現的,都是由web.config中的globalization結點指定的。
這段代碼絕大部分運行是沒問題的,但遇到Post請求的AJax調用頁面時,就出錯了,得到的username值是亂碼。通過前面兩篇的分析可知:Ajax請求時,頁面請求Header中加了“Content-Type: text/html; charset=utf8”,Server.UrlDecode()解碼方式變成了utf-8,亂碼自然產生了。問題解決方式是解碼時指定編碼方式,不要再用依賴於上下文的函數解碼了,可以改為“HttpUtility.UrlDecode(Request.Cookies["username"].Value, System.Text.Encoding.GetEncoding("GB2312"))”。

<form id="form1" runat="server"> <div> <input type="button" name="btnAjaxPost" value="AJax提交" onclick="Ajax()" /> <div id="divMessage" style="color: red"></div> </div> </form> <script type="text/javascript"> function Ajax() { $.ajax({ type: "POST", url: "LoginValidateCookie.aspx", data: { name: "name" }, success: function (data) { $("#divMessage").html(data); } }); } </script>
2.Url地址欄中的中文參數
有些頁面地址,由於某些原因帶了中文參數(如http://localhost:52443/Encode/EncodeTest.aspx?username=北京),而這些地址又可能已經被baidu等搜索引擎收錄,因此不能單靠生成新地址規則方式解決,項目必須做到兼容帶中文參數的地址。
如果是類似示例中的邏輯,中文參數為系統用戶的用戶名,則可以采用先用Request.QueryString方式獲取,得到username如果在系統中存在,則認為得到的參數是正確的;如果username在系統中不存在,則認為可能是因為參數中文亂碼原因引起的,再用NameValueCollection方式獲取一次,解碼方式和系統解碼是不一樣的(系統配置的是GB2312,則指定用utf-8解)。
string username = Request.QueryString["username"]; //如果通過Request方式獲取參數亂碼,則可以通過解析Request.Url.Query的方式獲取參數 NameValueCollection parames = HttpUtility.ParseQueryString(Request.Url.Query, Encoding.UTF8); string username2 = parames["username"];
如果中文參數值是任意值,無法判斷是正常值還是亂碼,可能就要根據不同瀏覽器類型,判斷用GB2312解碼還是utf-8解碼了。當然為避免不必要的麻煩,盡量url地址中不要含有中文參數(可通過編碼來解決,工行網站就是這么干的,url中的中文用了utf-8編碼http://www.icbc.com.cn/ICBC/%e5%ae%a2%e6%88%b7%e6%9c%8d%e5%8a%a1/%e7%83%ad%e7%82%b9%e9%97%ae%e7%ad%94/%e4%b8%aa%e4%ba%ba%e7%94%b5%e5%ad%90%e9%93%b6%e8%a1%8c/default.htm)。