Uri.EscapeDataString很奇怪

为什么EscapeDataString在.NET 4和4.5之间表现不同? 输出是

  • Uri.EscapeDataString("-_.!~*'()") => "-_.!~*'()"

  • Uri.EscapeDataString("-_.!~*'()") => "-_.%21~%2A%27%28%29"

文档

默认情况下,EscapeDataString方法将除RFC 2396非保留字符之外的所有字符转换为hex表示forms。 如果启用了国际资源标识符(IRI)或国际化域名(IDN)解析,则EscapeDataString方法将除RFC 3986非保留字符之外的所有字符转换为其hex表示forms。 在转义之前,所有Unicode字符都将转换为UTF-8格式。

作为参考,非保留字符在RFC 2396中定义如下:

 unreserved = alphanum | mark mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | (" | ")" 

在RFC 3986中 :

 ALPHA / DIGIT / "-" / "." / "_" / "~" 

源代码

看起来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的值确定,这似乎是矛盾的。 有人可以解决这个问题吗?

在系统function及其行为方面,4.5与4.0相比已经做了很多改变。 你可以看一下这个post

与我的开发机器相比,为什么Uri.EscapeDataString在我的CI服务器上返回不同的结果?

要么

你可以直接转到以下链接

http://msdn.microsoft.com/en-us/library/hh367887(v=vs.110).aspx

所有这一切都来自世界各地用户的意见。