过去一天左右我做了一些研究,我想我有一些关于这方面的信息。
当您使用 Request.Querystring 或 HttpUtility.UrlDecode(或 Encode)时,它使用的是在 web.config(或 .config 层次结构,如果您没有的话)的元素(特别是 requestEncoding 属性)中指定的编码指定)---不是 Encoding.Default,它是您服务器的默认编码。
当您将编码设置为 UTF-8 时,单个 unicode 字符可以编码为 2 %xx 十六进制值。当给定整个值时,它也会以这种方式解码。
如果您的 UrlDecoding 使用的编码与 url 的编码不同,您将得到不同的结果。
由于 HttpUtility.UrlEncode 和 UrlDecode 可以采用编码参数,因此尝试使用 ANSI 代码页进行编码很诱人,但如果您有浏览器支持(显然旧版本不支持),UTF-8 是正确的选择UTF-8)。您只需要确保正确设置并且双方都可以正常工作。
UTF-8 似乎是默认编码:(来自.net 反射器 System.Web.HttpRequest)
internal Encoding QueryStringEncoding
{
get
{
Encoding contentEncoding = this.ContentEncoding;
if (!contentEncoding.Equals(Encoding.Unicode))
{
return contentEncoding;
}
return Encoding.UTF8;
}
}
按照路径查找 this.ContentEncoding 会导致您(也在 HttpRequest 中)
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);
}
}
要回答您关于 Request.Url.Quer 和 Request.QueryString 之间区别的具体问题...这里是 HttpRequest 如何构建其 Url 属性:
public Uri Url
{
get
{
if ((this._url == null) && (this._wr != null))
{
string queryStringText = this.QueryStringText;
if (!string.IsNullOrEmpty(queryStringText))
{
queryStringText = "?" + HttpEncoder.CollapsePercentUFromStringInternal(queryStringText, this.QueryStringEncoding);
}
if (AppSettings.UseHostHeaderForRequestUrl)
{
string knownRequestHeader = this._wr.GetKnownRequestHeader(0x1c);
try
{
if (!string.IsNullOrEmpty(knownRequestHeader))
{
this._url = new Uri(this._wr.GetProtocol() + "://" + knownRequestHeader + this.Path + queryStringText);
}
}
catch (UriFormatException)
{
}
}
if (this._url == null)
{
string serverName = this._wr.GetServerName();
if ((serverName.IndexOf(':') >= 0) && (serverName[0] != '['))
{
serverName = "[" + serverName + "]";
}
this._url = new Uri(this._wr.GetProtocol() + "://" + serverName + ":" + this._wr.GetLocalPortAsString() + this.Path + queryStringText);
}
}
return this._url;
}
}
您可以看到它使用 HttpEncoder 类进行解码,但它使用相同的 QueryStringEncoding 值。
由于我已经在这里发布了很多代码并且任何人都可以获得 .NET Reflector,所以我将整理其余部分。 QueryString 属性来自 HttpValueCollection,它使用 FillFromEncodedBytes 方法最终调用 HttpUtility.UrlDecode(上面设置了 QueryStringEncoding 值),最终调用 HttpEncoder 对其进行解码。
他们似乎确实使用了不同的方法来解码查询字符串的实际字节,但他们使用的编码似乎是相同的。
有趣的是,HttpEncoder 有这么多似乎做同样事情的函数,所以这些方法可能存在差异,这可能会导致问题。