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

时间:2012-08-17 10:38:16

标签: c# .net vb.net

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

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

Imports NUnit.Framework

<TestFixture()>
Public Class UriTest

   <Test()>
    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中运行此功能成功,在安装了VS2012的计算机上的VS2010中运行此功能失败。两者都使用最新版本的NCrunch和NuGet的NUnit。

Machine without VS2012 Install

Machine with VS2012 Install

来自失败断言的消息是

  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,那么它就会成功。

2 个答案:

答案 0 :(得分:8)

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

此外,还有breaking changes documented in System.Uri。其中一个说 Unicode规范化形式C(NFC)将不再在URI的非主机部分上执行。我不确定这是否适用于您的情况,但它可以作为您调查错误的良好起点。

答案 1 :(得分:6)

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

以下逐字引用的connect report更多详情。

  

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

     

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

     

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

     

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

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

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

     

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

     

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

     

THX,

     

网络团队