VS2012安装后System.Uri.ToString行为更改

在开发机器上安装VS2012 Premium后,unit testing失败,因此开发人员修复了该问题。 当更改被推送到TeamCity时,unit testing失败。 除了升级的解决方案文件与VS2012兼容之外,项目没有改变。 它仍然以.net框架4.0为目标

我已经将问题Uri.ToString为在调用Uri.ToString时转义unicode字符的问题。 以下代码复制了该行为。

 Imports NUnit.Framework  Public Class UriTest  Public Sub UriToStringUrlDecodes() Dim uri = New Uri("http://www.example.org/test?helloworld=foo%B6bar") Assert.AreEqual("http://www.example.org/test?helloworld=foo¶bar", uri.ToString()) End Sub End Class 

在未安装VS2012的计算机上在VS2010中运行此function成功,在VS2010上安装VS2012的计算机上运行此function失败。 两者都使用最新版本的NCrunch和NuGet的NUnit。

没有VS2012的机器安装

VS2012机器安装

来自失败断言的消息是

  Expected string length 46 but was 48. Strings differ at index 42. Expected: "http://www.example.org/test?helloworld=foo¶bar" But was: "http://www.example.org/test?helloworld=foo%B6bar" -----------------------------------------------------^ 

.NET 4和.NET 4.5的MSDN文档显示, ToString不应对此字符进行编码,这意味着旧行为应该是正确的。

 A String instance that contains the unescaped canonical representation of the Uri instance. All characters are unescaped except #, ?, and %. 

安装VS2012后,正在转义该unicode字符。

VS2012计算机上System.dll的文件版本为4.0.30319.17929

构建服务器上的System.dll的文件版本是4.0.30319.236

忽略我们使用uri.ToString() ,我们正在测试什么以及任何潜在的解决方法。 任何人都可以解释为什么这种行为似乎已经改变,或者这是一个错误?

编辑,这是C#版本

 using System; using NUnit.Framework; namespace SystemUriCSharp { [TestFixture] public class UriTest { [Test] public void UriToStringDoesNotEscapeUnicodeCharacters() { var uri = new Uri(@"http://www.example.org/test?helloworld=foo%B6bar"); Assert.AreEqual(@"http://www.example.org/test?helloworld=foo¶bar", uri.ToString()); } } } 

进一步调查,如果我以.NET 4.0或.NET 4.5为目标,测试失败,如果我将其切换到.NET 3.5,那么它就会成功。

.NET Framework 4.5中引入了一些更改,它与VS2012一起安装,并且(据我所知)也称为“就地升级”。 这意味着它实际上升级了.NET Framework 4。

此外, System.Uri中记录了重大更改 。 其中一个表示将不再对URI的非主机部分执行forms化C(NFC)的Unicode规范化 。 我不确定这是否适用于您的情况,但它可以作为您调查错误的良好起点。

此更改与早期.NET版本的问题有关,现在已经更改为更符合标准。 %B6是UTF-16,但根据标准,UTF-8应该在Uri中使用,这意味着它应该是%C2%B6 。 因此%B6不是UTF-8,现在它被正确忽略而不被解码。

联系报告中的更多详细信息在下面逐字引用。

.NET 4.5具有增强且更兼容的RFC 3987应用程序,它支持URI的IRI解析规则。 IRI是国际资源标识符。 这允许非ASCII字符在要解析的URI / IRI字符串中。

在.NET 4.5之前,我们对IRI进行了一些不一致的处理。 我们有一个app.config条目,默认值为false,您可以打开:

做了一些IRI处理/解析。 但是,它有一些问题。 特别是它允许不正确的百分比编码处理。 根据RFC 3987,URI / IRI字符串中的百分比编码项应该是百分比编码的UTF-8八位字节。它们不被解释为百分比编码的UTF-16。 因此,根据UTF-8处理“%B6”是不正确的,并且不会发生解码。 ¶的正确UTF-8编码实际上是“%C2%B6”。

如果您的字符串是这样的:

  string strUri = @"http://www.example.com/test?helloworld=foo%C2%B6bar"; 

然后它将在ToString()方法中进行规范化,并解码和删除百分比编码。

您能否提供有关您的应用程序需求和ToString()方法的更多信息? 通常,我们建议使用Uri对象的AbsoluteUri属性来满足大多数规范化需求。

如果此问题阻止了您的应用程序开发和业务需求,请通过“netfx45compat at Microsoft dot com”电子邮件地址告知我们。

谢谢,

网络团队

在那种情况下,你不能这样做。 主要问题是字符“¶”。

在.Net中,我们在角色上遇到了问题¶。 你可以对此进行研究。

逐个获取uri’参数。 将它们加一个并进行比较。 也许你可以使用“¶”字符的方法来创建它或替换它。

例如;

 Dim uri = New Uri("http://www.example.org/test?helloworld=foo%B6bar") Assert.AreEqual("http://www.example.org/test?helloworld=foo¶bar", uri.Host+uri.AbsolutePath+"?"+uri.Query) 

那会有用

uri.AbsolutePath:/ test

url.Host:http://www.example.org

uri.Query:helloworld =foo¶bar