Подтвердить что ты не робот

Изменение поведения 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, тогда он преуспеет.

4b9b3361

Ответ 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