Mudança de comportamento do System.Uri.ToString após a instalação do VS2012

Depois de instalar o VS2012 Premium em uma máquina de desenvolvimento, um teste de unidade falhou, então o desenvolvedor resolveu o problema. Quando as alterações foram enviadas para o TeamCity, o teste da unidade falhou. O projeto não mudou além do arquivo de solução que está sendo atualizado para ser compatível com o VS2012. Ainda é alvo do framework .net 4.0

Eu Uri.ToString o problema para um problema com caracteres unicode sendo escapados ao chamar Uri.ToString . O código a seguir replica o comportamento.

 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 

Executar isso no VS2010 em uma máquina que não tem VS2012 instalado é bem-sucedida, executando isso no VS2010 em uma máquina com o VS2012 instalado falha. Ambos usando a versão mais recente do NCrunch e NUnit da NuGet.

Máquina sem VS2012 Instala

Máquina com instalação do VS2012

As mensagens da declaração falhada são

  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" -----------------------------------------------------^ 

A documentação no MSDN para .NET 4 e .NET 4.5 mostra que ToString não deve codificar esse caractere, o que significa que o comportamento antigo deve ser o correto.

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

Depois de instalar o VS2012, esse caractere unicode está sendo escapado.

A versão do arquivo do System.dll na máquina com o VS2012 é 4.0.30319.17929

A versão do arquivo do System.dll no servidor de compilation é 4.0.30319.236

Ignorando os méritos de por que estamos usando uri.ToString() , o que estamos testando e qualquer possível trabalho. Alguém pode explicar por que esse comportamento parece ter mudado, ou isso é um bug?

Edite, aqui está a versão 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()); } } } 

Um pouco de investigação adicional, se eu visar o .NET 4.0 ou o .NET 4.5, os testes falharão, se eu mudar para o .NET 3.5, então ele será bem-sucedido.

Existem algumas alterações introduzidas no .NET Framework 4.5, que é instalado junto com o VS2012, e que também é (no melhor de meu conhecimento) um chamado “upgrade in loco”. Isso significa que ele realmente atualiza o .NET Framework 4.

Além disso, há alterações significativas documentadas em System.Uri . Um deles diz que a forma de normalização Unicode C (NFC) não será mais executada em partes não hospedadas de URIs . Não tenho certeza se isso é aplicável ao seu caso, mas pode servir como um bom ponto de partida para a investigação do erro.

A alteração está relacionada a problemas com versões anteriores do .NET, que agora mudaram para se tornar mais compatíveis com os padrões. %B6 é UTF-16, mas de acordo com os padrões UTF-8 deve ser usado no Uri, o que significa que deve ser %C2%B6 . Então, como %B6 não é UTF-8, ele agora é ignorado e não é decodificado corretamente.

Mais detalhes do relatório de conexão citado em textuais abaixo.

O .NET 4.5 aprimorou e tornou mais compatível a aplicação do RFC 3987, que suporta as regras de análise do IRI para URIs. IRIs são identificadores de resources internacionais. Isso permite que caracteres não-ASCII estejam em uma sequência de URI / IRI a ser analisada.

Antes do .NET 4.5, tivemos algumas manipulações inconsistentes de IRIs. Tivemos uma input app.config com um padrão de falso que você pode ativar:

que fez alguma manipulação / análise IRI. No entanto, teve alguns problemas. Em particular, permitia manipulação incorreta de porcentagem de codificação. Os itens com codificação percentual em uma sequência URI / IRI devem ser octetos UTF-8 codificados por porcentagem, de acordo com a RFC 3987. Eles não são interpretados como UTF-16 codificados por porcentagem. Portanto, manipular “% B6” está incorreto de acordo com o UTF-8 e nenhuma decodificação ocorrerá. A codificação UTF-8 correta para ¶ é, na verdade, “% C2% B6”.

Se a sua string foi esta:

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

Em seguida, ele será normalizado no método ToString () e a codificação percentual será decodificada e removida.

Você pode fornecer mais informações sobre suas necessidades de aplicativo e o uso do método ToString ()? Geralmente, recomendamos a propriedade AbsoluteUri do object Uri para a maioria das necessidades de normalização.

Se esse problema estiver bloqueando o desenvolvimento de aplicativos e as necessidades de negócios, informe-nos por meio do endereço de e-mail “netfx45compat no Microsoft dot com”.

THX,

Equipa de Networking

Nessa situação você não pode fazer assim. A questão principal é o caractere “¶”.

No .net, temos um problema no personagem ¶. Você pode fazer uma pesquisa sobre isso.

Pegue os parâmetros do uri ‘um por um. Adicione-os por um e compare-os. Pode ser que você possa usar um método para o caractere “¶” para criá-lo ou substituí-lo.

Por exemplo;

 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) 

isso vai funcionar

uri.AbsolutePath: / test

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

uri.Query: helloworld = foo¶bar