This morning I was asked a question by a colleague: I said that the parameters received were garbled, let me help solve it.
The platform my colleague is responsible for is built Ext.js framework, and the web.config configuration file is configured with the global "GB2312" encoding:
<globalization requestEncoding="gb2312" responseEncoding="gb2312" fileEncoding="gb2312" culture="zh-CN"/>
When the frontend submits the "Chinese text", the backend receives garbled characters with Request.QueryString["xxx"].
No matter how you decode with System.Web.HttpUtility.UrlDecode("xxx", "encoding type"), it doesn't work.
Principle description: 1: The first thing to determine is that when the client's URL parameters are submitted, Ext.js will encode them before submitting them, and the client's encoding is UTF-8 encoding by default
2: Then why is it garbled when receiving parameters with Request.QueryString["xxx"]?
We reverse the compilation step by step, 2.1: Look at the code for the QueryString property:
- Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->public NameValueCollection 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;
- }
- }
Copy code
2.2: Cut into the FillInQueryStringCollection() method
- Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->private void 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);
-
- }
- }
Copy code
2.3: Cut: QueryStringEncoding
- Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->internal Encoding 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);
- }
- }
Copy codeFrom the QueryStringEncoding code, the system defaults to the encoding method of the globalization configuration node, and if not, the default is UTF-8 encoding 2.4: Cut into FillFromString(string s, bool urlencoded, Encoding encoding)
- 代码有点长,就折叠起来了
- Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->internal void FillFromString(string s, bool urlencoded, Encoding encoding)
- {
- int num = (s != null) ? s.Length : 0;
- for (int i = 0; i < num; i++)
- {
- int startIndex = i;
- int num4 = -1;
- while (i < num)
- {
- char ch = s[i];
- if (ch == '=')
- {
- if (num4 < 0)
- {
- num4 = i;
- }
- }
- else if (ch == '&')
- {
- break;
- }
- i++;
- }
- string str = null;
- string str2 = null;
- if (num4 >= 0)
- {
- str = s.Substring(startIndex, num4 - startIndex);
- str2 = s.Substring(num4 + 1, (i - num4) - 1);
- }
- else
- {
- str2 = s.Substring(startIndex, i - startIndex);
- }
- if (urlencoded)//外面的传值默认是true,所以会执行以下语句
- {
- base.Add(HttpUtility.UrlDecode(str, encoding), HttpUtility.UrlDecode(str2, encoding));
- }
- else
- {
- base.Add(str, str2);
- }
- if ((i == (num - 1)) && (s[i] == '&'))
- {
- base.Add(null, string.Empty);
- }
- }
- }
Copy codeFrom this point we find that all parameter inputs are called once: HttpUtility.UrlDecode(str2, encoding);
When client js submits Chinese to the server in utf-8 encoding, when receiving it with Request.QueryString, it will first decode it once with gb2312 configured by globalization, resulting in garbled characters.
1: The JS encoding method is URT-8
2: The server side has configured the default to GB2312
3: Request.QueryString will call HttpUtility.UrlDecode by default to decode the received parameters with system configuration encoding.
1: The system selects the default encoding in the following order: http request header - >globalization configuration node - default UTF-8
2: When entering the URL directly into Chinese, different browsers may handle it differently, for example: IE does not encode and submits directly, Firefox submits the URL after GB2312 encoding.
3: For unencoded "Chinese characters", after using Request.QueryString internal call HttpUtility.UrlDecode, by gb2312->utf-8,
If the Chinese character is not found, it will be converted to "%ufffd" by default, resulting in irreversible garbled characters.
4: The road to resolution Knowing the principle, there are many ways to solve it: 1: The global unification is UTF-8 encoding, which saves trouble and worry.
2: When GB2312 is globally specified, the url is Chinese, and js must be encoded, such as ext.js framework.
In this way, you can only handle it specially, specifying the encoding and decoding on the server side. Because the default system calls HttpUtility.UrlDecode("xxx", the encoding of the system configuration) once, So you call HttpUtility.UrlEncode("xxx", the encoding configured by the system) again to return to the original urt-8 encoding parameter
Then use HttpUtility.UrlDecode("xxx", utf-8) to decode it. string aaa = request. Request.QueryString["admin"]; Homeowner string a1 = HttpUtility.UrlEncode(aaa, System.Text.Encoding.GetEncoding("GB2312")); string a2 = HttpUtility.UrlDecode(a1,System.Text.Encoding.UTF8);
|