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

Chr*_*ver 18 .net c# vb.net

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

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

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
Run Code Online (Sandbox Code Playgroud)

在没有安装VS2012的机器上在VS2010中运行此功能成功,在安装了VS2012的机器上的VS2010中运行此功能失败.两者都使用最新版本的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"
  -----------------------------------------------------^
Run Code Online (Sandbox Code Playgroud)

.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 %.
Run Code Online (Sandbox Code Playgroud)

安装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());
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

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

Fre*_*örk 8

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

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


Chr*_*ver 6

此更改与早期.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";
Run Code Online (Sandbox Code Playgroud)

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

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

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

谢谢,

网络团队