Создание Uri в .NET автоматически urldecodes все параметры из переданной строки

Предположим, что я хочу создать объект Uri из следующей строки:

string url = @"http://someserver.com?param1=1&url=http%3a%2f%2fwww.otherserver.com";
Uri uri = new Uri(url, UriKind.Absolute);

Ожидаемый результат:

http://someserver.com?param1=1&url=http%3a%2f%2fwww.otherserver.com 

Получено:

http://someserver.com/?param1=1&url=http://www.otherserver.com

То же поведение наблюдается во многих связанных методах, которые позволяют создавать Uri: Uri.TryCreate, UriBuilder.Uri и т.д.

Как получить Uri, который сохранит исходный кодированный параметр?

Ответ 1

Это поведение задокументировано:

Как часть канонизации в конструкторе для некоторых схем, экранированные представления уплотняются. Схемы, для которых URI будет компактные экранированные последовательности включают в себя следующее: файл, http, https, net.pipe и net.tcp. Для всех других схем экранированные последовательности не уплотнен. Например: если вы процентов кодируете две точки ".." как "% 2E% 2E", тогда конструктор URI будет уплотнять эту последовательность для некоторых схем. Например, следующий пример кода показывает URI конструктор для схемы http.

Таким образом, одно временное решение может временно использовать пользовательскую схему (например, leavemealone://) для создания объектов URL (возможно, через UriBuilder?).

Ответ 2

Как вы "получили" URL? Если я наведите указатель мыши на него в Visual Studio, он действительно отобразит декодированный URL.

Но всякий раз, когда я обращаюсь к нему через свойство AbsoluteUri, он показывает кодированный URL.

Ответ 3

В .NET4 вы можете отключить сжатие Uri для определенной схемы через конфигурацию:

<configuration>
  <uri>
    <schemeSettings>
      <add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes"/>
    </schemeSettings>
  </uri>
</configuration>

Обратите внимание, что есть последствия для безопасности, связанные с отключением поведения по умолчанию.

Ответ 4

В моем случае я решил это, возвращая метод ToString() класса UriBuilder вместо использования свойства Uri того же класса.