Изменение поведения System.Uri.ToString после установки VS2012
После установки VS2012 Premium на dev-машине произошел сбой unit test, поэтому разработчик исправил проблему. Когда изменения были перенесены в TeamCity, сбой unit test. Проект не изменился, кроме файла решения, который был обновлен, чтобы быть совместимым с VS2012. Он по-прежнему нацелен на .net framework 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
Запуск этого в VS2010 на компьютере, на котором не установлен VS2012, выполняется успешно, при запуске этого в VS2010 на машине с установленным VS2012 происходит сбой. Оба используют последнюю версию NCrunch и NUnit от NuGet.
![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"
-----------------------------------------------------^
Документация на MSDN для .NET 4 и .NET 4.5 показывает, что ToString
не должен кодировать этот символ, что означает, что старое поведение должно быть правильным.
A String instance that contains the unescaped canonical representation of the Uri instance. All characters are unescaped except #, ?, and %.
После установки VS2012 этот символ юникода экранируется.
Файловая версия System.dll на машине с VS2012 - 4.0.30319.17929
Файловая версия System.dll на сервере сборки 4.0.30319.236
Игнорируя достоинства использования uri.ToString()
, то, что мы тестируем, и любая потенциальная работа. Может ли кто-нибудь объяснить, почему это поведение, похоже, изменилось или это ошибка?
Изменить, вот версия С#
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, тогда он преуспеет.
Ответы
Ответ 1
Это изменение связано с проблемами с более ранними версиями .NET, которые теперь изменены, чтобы стать более совместимыми со стандартами. %B6
является UTF-16, но в соответствии с стандартами UTF-8 следует использовать в Uri, что означает, что оно должно быть %C2%B6
. Так как %B6
не UTF-8, он теперь корректно игнорируется и не декодируется.
Подробнее из отчета connect, приведенного ниже.
.NET 4.5 имеет расширенное и совместимое приложение RFC 3987 который поддерживает правила синтаксического анализа IRI для URI. ИРИ являются международными Идентификаторы ресурсов. Это позволяет символам, отличным от ASCII, находиться в Строка URI/IRI, подлежащая анализу.
До .NET 4.5 у нас была некоторая непоследовательная обработка IRI. Мы имеем запись app.config со значением по умолчанию false, который вы можете включить:
который выполнял обработку и обработку IRI. Однако у него были некоторые проблемы. В в частности, он допускал неправильную обработку кодировки процентов. Предполагается, что элементы, закодированные в процентах, в строке URI/IRI процентные кодированные октеты UTF-8 в соответствии с RFC 3987. Они не являются интерпретируется как процентное кодирование UTF-16. Таким образом, обработка "% B6" неверна согласно UTF-8, и декодирования не будет. Правильный UTF-8 кодирование для ¶ на самом деле "% C2% B6".
Если вместо этого была ваша строка:
string strUri = @"http://www.example.com/test?helloworld=foo%C2%B6bar";
Затем он будет нормализован в методе ToString() и процентное кодирование декодируется и удаляется.
Можете ли вы предоставить больше информации о потребностях вашего приложения и использование метода ToString()? Обычно мы рекомендуем AbsoluteUri свойство объекта Uri для большинства потребностей нормализации.
Если эта проблема блокирует разработку вашего приложения и бизнес необходимо, пожалуйста, сообщите нам через "netfx45compat at Microsoft dot com".
спасибо,
Сетевая команда
Ответ 2
В .NET Framework 4.5 внесены некоторые изменения, которые установлены вместе с VS2012, а также (насколько мне известно) так называемое обновление на месте. Это означает, что он фактически обновляет .NET Framework 4.
Кроме того, существуют изменения, зафиксированные в System.Uri. Один из них говорит, что форма нормализации Unicode C (NFC) больше не будет выполняться на участках URI, отличных от хоста. Я не уверен, применим ли это к вашему делу, но это может послужить хорошей отправной точкой в вашем исследовании ошибки.
Ответ 3
В этой ситуации вы не можете так поступать.
Основная проблема - символ "¶".
В .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