Uri.EscapeDataString 怪异
Posted
技术标签:
【中文标题】Uri.EscapeDataString 怪异【英文标题】:Uri.EscapeDataString weirdness 【发布时间】:2014-09-17 17:00:29 【问题描述】:为什么 EscapeDataString 在 .NET 4 和 4.5 之间的行为不同?输出是
Uri.EscapeDataString("-_.!~*'()") => "-_.!~*'()"
Uri.EscapeDataString("-_.!~*'()") => "-_.%21~%2A%27%28%29"
The documentation
默认情况下,EscapeDataString 方法转换所有字符,除了 将 RFC 2396 未保留字符转换为十六进制 表示。如果国际资源标识符 (IRI) 或 启用国际化域名 (IDN) 解析, EscapeDataString 方法转换所有字符,除了 RFC 3986 未保留的字符,以它们的十六进制表示。全部 Unicode 字符在转义前转换为 UTF-8 格式。
供参考,RFC 2396中的非保留字符定义如下:
unreserved = alphanum | mark
mark = "-" | "_" | "." | "!" | "~" | "*" | "'" |
(" | ")"
在RFC 3986:
ALPHA / DIGIT / "-" / "." / "_" / "~"
The source code
看起来EscapeDataString的每个字符是否被转义大致是这样确定的
is unicode above \x7F
? PERCENT ENCODE
: is a percent symbol
? is an escape char
? LEAVE ALONE
: PERCENT ENCODE
: is a forced character
? PERCENT ENCODE
: is an unreserved character
? PERCENT ENCODE
在最后检查“是非保留字符”时,会在 RFC2396 和 RFC3986 之间进行选择。该方法的源代码逐字为
internal static unsafe bool IsUnreserved(char c)
if (Uri.IsAsciiLetterOrDigit(c))
return true;
if (UriParser.ShouldUseLegacyV2Quirks)
return (RFC2396UnreservedMarks.IndexOf(c) >= 0);
return (RFC3986UnreservedMarks.IndexOf(c) >= 0);
那段代码指的是
private static readonly UriQuirksVersion s_QuirksVersion =
(BinaryCompatibility.TargetsAtLeast_Desktop_V4_5
// || BinaryCompatibility.TargetsAtLeast_Silverlight_V6
// || BinaryCompatibility.TargetsAtLeast_Phone_V8_0
) ? UriQuirksVersion.V3 : UriQuirksVersion.V2;
internal static bool ShouldUseLegacyV2Quirks
get
return s_QuirksVersion <= UriQuirksVersion.V2;
混乱
文档说 EscapeDataString 的输出取决于是否启用了 IRI/IDN 解析,而源代码说输出由 TargetsAtLeast_Desktop_V4_5
的值决定,这似乎是矛盾的。有人可以解决这个问题吗?
【问题讨论】:
这个问题帮助我弄清楚了为什么在 .Net 4.5 下我没有得到预期的行为,尽管我一开始并没有意识到。我应该更仔细地阅读源代码上的 cmets!谢谢!我的 *** 问题:***.com/questions/41006873/… 【参考方案1】:与 4.0 相比,4.5 在系统功能和行为方式方面做了很多更改。 你可以看看这个帖子
Why does Uri.EscapeDataString return a different result on my CI server compared to my development machine?
或
你可以直接去以下链接
http://msdn.microsoft.com/en-us/library/hh367887(v=vs.110).aspx
所有这一切都来自世界各地用户的投入。
【讨论】:
以上是关于Uri.EscapeDataString 怪异的主要内容,如果未能解决你的问题,请参考以下文章
如何让 Uri.EscapeDataString 符合 RFC 3986
通过“HttpUtility.UrlEncode”和“Uri.EscapeDataString”在 GET API 请求中编码撇号会出错
EscapeUriString 和 EscapeDataString 有啥区别?
Owin的URL编码怎么搞?以前都是HttpUtility.UrlEncode之类的,现在连system.web都没了,肿么办?