轉載出處:http://www.cnblogs.com/cyq1162/archive/2010/11/29/1891124.html
起因:
實際情景:
<globalization requestEncoding="gb2312" responseEncoding="gb2312" fileEncoding="gb2312" culture="zh-CN"/>
當前臺提交“中文文字”時,後臺用Request.QueryString["xxx"]接收到的是亂碼。
無論用System.Web.HttpUtility.UrlDecode("xxx","編碼類型")怎麼解碼都無效。
原理說明:
1:首先確定的是:客戶端的url參數在提交時,Ext.js會對其編碼再提交,而客戶端的編碼默認是utf-8編碼
2:那爲什麼用Request.QueryString["xxx"]接收參數時,收到的會是亂碼?
我們步步反編繹,
2.1:看QueryString屬性的代碼:
{
get
{
if (this._queryString == null)
{
this._queryString = new HttpValueCollection();
if (this._wr != null)
{
this.FillInQueryStringCollection();//重點代碼切入點
}
this._queryString.MakeReadOnly();
}
if (this._flags[1])
{
this._flags.Clear(1);
ValidateNameValueCollection(this._queryString, "Request.QueryString");
}
return this._queryString;
}
}
2.2:切入 FillInQueryStringCollection()方法
{
byte[] queryStringBytes = this.QueryStringBytes;
if (queryStringBytes != null)
{
if (queryStringBytes.Length != 0)
{
this._queryString.FillFromEncodedBytes(queryStringBytes, this.QueryStringEncoding);
}
}//上面是對流字節的處理,即文件上傳之類的。
else if (!string.IsNullOrEmpty(this.QueryStringText))
{
//下面這句是對普通文件提交的處理:FillFromString是個切入點,編碼切入點是:this.QueryStringEncoding
this._queryString.FillFromString(this.QueryStringText, true, this.QueryStringEncoding);
}
}
2.3:切入:QueryStringEncoding
{
get
{
Encoding contentEncoding = this.ContentEncoding;
if (!contentEncoding.Equals(Encoding.Unicode))
{
return contentEncoding;
}
return Encoding.UTF8;
}
}
//點擊進入this.ContentEncoding則爲:
public Encoding ContentEncoding
{
get
{
if (!this._flags[0x20] || (this._encoding == null))
{
this._encoding = this.GetEncodingFromHeaders();
if (this._encoding == null)
{
GlobalizationSection globalization = RuntimeConfig.GetLKGConfig(this._context).Globalization;
this._encoding = globalization.RequestEncoding;
}
this._flags.Set(0x20);
}
return this._encoding;
}
set
{
this._encoding = value;
this._flags.Set(0x20);
}
}
說明:
2.4:切入 FillFromString(string s, bool urlencoded, Encoding encoding)
說明:
3:結論出來了
所有的起因爲:
2:服務端又配置了默認爲gb2312
3:Request.QueryString默認又會調用HttpUtility.UrlDecode用系統配置編碼去解碼接收參數。
文章補充:
2:在Url直接輸入中文時,不同瀏覽器處理方式可能不同如:ie不進行編碼直接提交,firefox對url進行gb2312編碼後提交。
3:對於未編碼“中文字符”,使用Request.QueryString時內部調用HttpUtility.UrlDecode後,由gb2312->utf-8時,
如果查不到該中文字符,默認轉成"%ufffd",因此出現不可逆亂碼。
4:解決之路
知道了原理,解決的方式也有多種多樣了:
1:全局統一爲UTF-8編碼,省事又省心。
2:全局指定了GB2312編碼時,url帶中文,js非編碼不可,如ext.js框架。
因爲默認系統調用了一次HttpUtility.UrlDecode("xxx",系統配置的編碼),
因此你再調用一次HttpUtility.UrlEncode("xxx",系統配置的編碼),返回到原始urt-8編碼參數
再用HttpUtility.UrlDecode("xxx",utf-8),解碼即可。
5:其它說明:默認對進行一次解碼的還包括URI屬性,而Request.RawUrl則爲原始參數