Как вы UrlEncode без использования System.Web?

310

Я пытаюсь написать клиентское приложение Windows, которое вызывает веб-сайт для данных. Чтобы свести установку к минимуму, я пытаюсь использовать только dll в .NET Framework Client Profile . Проблема в том, что мне нужно UrlEncode некоторых параметров, есть ли простой способ сделать это без импорта System.Web.dll, который не является частью Client Pofile?

Мартин Браун
источник
Не могли бы вы показать, как вы выполняете звонок на веб-сайт? Может быть, есть что-то, что можно сделать там.
Дарин Димитров
Из любопытства, как вы называете сайт данными без использования System.Web?
Патрик Макдональд
@ Патрик, он, вероятно, использует WebRequestили WebClient. Вот почему я спросил об этом конкретном коде, потому что есть вещи, которые можно сделать с правильными данными кодирования URL.
Дарин Димитров
1
Я использую объект System.Net.WebRequest. Затем я вызываю GetRequestStream и записываю свои параметры Post в поток. Я также установил ContentType в «application / x-www-form-urlencoded».
Мартин Браун
1
Конечно, это в равной степени применимо, если я выполняю запрос GET и добавляю параметры в URL.
Мартин Браун

Ответы:

317

System.Uri.EscapeUriString() может быть проблематично с определенными символами, для меня это был знак числа / фунта '#' в строке.

Если это проблема для вас, попробуйте:

System.Uri.EscapeDataString() //Works excellent with individual values

Вот так ответ на вопрос, который объясняет разницу:

В чем разница между EscapeUriString и EscapeDataString?

и рекомендует использовать Uri.EscapeDataString()в любом аспекте.

ToddBFisher
источник
1
Неверно : blogs.msdn.com/b/yangxind/archive/2006/11/09/… У вас будут проблемы со знаком плюс, так как они не будут закодированы.
Крис Вебер
7
Это сообщение в блоге устарело, и у меня просто есть "Uri Escaped" полный URL, и все пробелы стали% 20, так что я думаю, что они это исправили. Я использую .Net 4.5.
Роди
EscapeDataString также не поддерживает очень длинные строки, если вы готовите данные для операции POST. stackoverflow.com/questions/6695208/…
Брон Дэвис
Uri.EscapeUriStringдействительно очень проблематично и не должно использоваться, поскольку он пытается что-то сделать (избегая полных URI), что на самом деле невозможно сделать последовательно. См. этот ответ для подробного объяснения.
Ливвен
Также космический персонаж.
Вакас Шаббир
252

В .Net 4.5+ используют WebUtility

Просто для форматирования я отправляю это как ответ.

Не могу найти хороших примеров, сравнивающих их так:

string testString = "http://test# space 123/text?var=val&another=two";
Console.WriteLine("UrlEncode:         " + System.Web.HttpUtility.UrlEncode(testString));
Console.WriteLine("EscapeUriString:   " + Uri.EscapeUriString(testString));
Console.WriteLine("EscapeDataString:  " + Uri.EscapeDataString(testString));
Console.WriteLine("EscapeDataReplace: " + Uri.EscapeDataString(testString).Replace("%20", "+"));

Console.WriteLine("HtmlEncode:        " + System.Web.HttpUtility.HtmlEncode(testString));
Console.WriteLine("UrlPathEncode:     " + System.Web.HttpUtility.UrlPathEncode(testString));

//.Net 4.0+
Console.WriteLine("WebUtility.HtmlEncode: " + WebUtility.HtmlEncode(testString));
//.Net 4.5+
Console.WriteLine("WebUtility.UrlEncode:  " + WebUtility.UrlEncode(testString));

Выходы:

UrlEncode:             http%3a%2f%2ftest%23+space+123%2ftext%3fvar%3dval%26another%3dtwo
EscapeUriString:       http://test#%20space%20123/text?var=val&another=two
EscapeDataString:      http%3A%2F%2Ftest%23%20space%20123%2Ftext%3Fvar%3Dval%26another%3Dtwo
EscapeDataReplace:     http%3A%2F%2Ftest%23+space+123%2Ftext%3Fvar%3Dval%26another%3Dtwo

HtmlEncode:            http://test# space 123/text?var=val&another=two
UrlPathEncode:         http://test#%20space%20123/text?var=val&another=two

//.Net 4.0+
WebUtility.HtmlEncode: http://test# space 123/text?var=val&another=two
//.Net 4.5+
WebUtility.UrlEncode:  http%3A%2F%2Ftest%23+space+123%2Ftext%3Fvar%3Dval%26another%3Dtwo

В .Net 4.5+ используют WebUtility.UrlEncode

Это похоже на репликацию HttpUtility.UrlEncode(до v4.0) для более распространенных символов:
Uri.EscapeDataString(testString).Replace("%20", "+").Replace("'", "%27").Replace("~", "%7E")
Примечание: EscapeUriStringсохранит допустимую строку URI, что заставит его использовать как можно больше символов открытого текста.

См. Этот ответ для таблицы, сравнивающей различные кодировки:
https://stackoverflow.com/a/11236038/555798

Разрывы строк Все перечисленные здесь (кроме HttpUtility.HtmlEncode) будут преобразованы "\n\r"в %0a%0dили%0A%0D

Пожалуйста, не стесняйтесь редактировать это и добавлять новые символы в мою тестовую строку, или оставить их в комментариях, и я отредактирую это.

тимин
источник
В моем случае я должен был использовать EscapeDataStringне то, EscapeUriStringчто мы кодировали возвраты каретки и переводы строк, и это требовало более агрессивного побегаEscapeDataString
David O'Meara
1
больше примеров, вы можете предоставить свои собственные тестовые случаи, если хотите. Вот пример его запуска и других методов кодирования, которые показывают различия dotnetfiddle.net/12IFw1
Маслоу
3
WebUtility.UrlEncode () и WebUtility.UrlDecode () - 4.5+. Они не существуют в 4.0.
Дерек Калвейт,
MSDN говорит: «Универсальная платформа Windows: доступно с 4.5, .NET Framework: доступно с 4.0» ...
Thymine
54

Ты можешь использовать

Uri.EscapeUriString (см http://msdn.microsoft.com/en-us/library/system.uri.escapeuristring.aspx )

Мэтью Манела
источник
Есть ли разница между этим и EscapeDataString?
Мартин Браун
3
Вы хотите использовать EscapeUriString. EscapeUriString попытается закодировать весь URL (включая http: // part), в то время как EscapeUriString понимает, какие части на самом деле должны быть закодированы
Мэтью Манела
1
Я вижу, поэтому в этом случае я, вероятно, хотел бы EscapeDataString, поскольку я могу передать URL в качестве параметра get. Я добавляю URL в этом случае.
Мартин Браун
5
@MatthewManela Я почти уверен, что ваш комментарий на октябрь должен прочитать EscapeDataString попытается кодировать ...
Маслоу
Не используйте Uri.EscapeUriString. Он не «понимает», какие части должны быть закодированы, это просто ошибочная попытка что-то сделать (избегая полных URI), что на самом деле невозможно сделать последовательно. Смотрите этот ответ для подробного объяснения.
Ливвен
20

Ответы здесь очень хорошие, но все же недостаточны для меня.

Я написал небольшой цикл, который сравнивает Uri.EscapeUriString с Uri.EscapeDataStringдля всех символов от 0 до 255.

ПРИМЕЧАНИЕ. Обе функции имеют встроенный интеллект: символы выше 0x80 сначала кодируются в кодировке UTF-8, а затем кодируются в процентах.

Вот результат:

******* Different *******

'#' -> Uri "#" Data "%23"
'$' -> Uri "$" Data "%24"
'&' -> Uri "&" Data "%26"
'+' -> Uri "+" Data "%2B"
',' -> Uri "," Data "%2C"
'/' -> Uri "/" Data "%2F"
':' -> Uri ":" Data "%3A"
';' -> Uri ";" Data "%3B"
'=' -> Uri "=" Data "%3D"
'?' -> Uri "?" Data "%3F"
'@' -> Uri "@" Data "%40"


******* Not escaped *******

'!' -> Uri "!" Data "!"
''' -> Uri "'" Data "'"
'(' -> Uri "(" Data "("
')' -> Uri ")" Data ")"
'*' -> Uri "*" Data "*"
'-' -> Uri "-" Data "-"
'.' -> Uri "." Data "."
'_' -> Uri "_" Data "_"
'~' -> Uri "~" Data "~"

'0' -> Uri "0" Data "0"
.....
'9' -> Uri "9" Data "9"

'A' -> Uri "A" Data "A"
......
'Z' -> Uri "Z" Data "Z"

'a' -> Uri "a" Data "a"
.....
'z' -> Uri "z" Data "z"

******* UTF 8 *******

.....
'Ò' -> Uri "%C3%92" Data "%C3%92"
'Ó' -> Uri "%C3%93" Data "%C3%93"
'Ô' -> Uri "%C3%94" Data "%C3%94"
'Õ' -> Uri "%C3%95" Data "%C3%95"
'Ö' -> Uri "%C3%96" Data "%C3%96"
.....

EscapeUriStringдолжен использоваться для кодирования URL, в то время EscapeDataStringкак должен использоваться, например, для кодирования содержимого Cookie, поскольку данные Cookie не должны содержать зарезервированные символы '='и ';'.

Elmue
источник
хороший анализ и разбивка здесь, очень полезно. если кто-то знает или знает о тестах производительности (сравнивая все три метода), это также было бы приятно увидеть
Шон Уилсон,
Это хороший анализ, и вы должны не использовать его Uri.EscapeUriString, поскольку экранирование полных URI невозможно сделать последовательно. Смотрите этот ответ для подробного объяснения.
Ливвен
16

В клиентском профиле System.dll имеется версия для использования в профиле клиента, класс System.Net.WebUtility. Вот ссылка MSDN:

WebUtility

Спрэг
источник
Я хотел бы отметить, что на странице справки для этого класса конкретно указано «Предоставляет методы для кодирования и декодирования URL-адресов при обработке веб-запросов». так что могло случиться так, что они не называли методы хорошо.
Джеймс Уайт
Хороший вопрос, скажи, почему бы тебе не проголосовать за брата;) этот голос преследует меня уже 2 года! JK ... но, честно говоря, вероятно, поэтому я разместил ссылку, к сожалению, я пользуюсь репутацией за ошибки в документах Microsoft ...
Sprague
11
Похоже, что UrlEncode и UrlDecode были добавлены только в WebUtility в версии 4.5 .Net.
Мартин Браун
8

Вот пример отправки запроса POST, который правильно кодирует параметры, используя application/x-www-form-urlencodedтип содержимого:

using (var client = new WebClient())
{
    var values = new NameValueCollection
    {
        { "param1", "value1" },
        { "param2", "value2" },
    };
    var result = client.UploadValues("http://foo.com", values);
}
Дарин димитров
источник
-3
System.Net.WebUtility.HtmlDecode
user3105093
источник
Класс WebUtility предоставляет методы для кодирования и декодирования URL-адресов при обработке веб-запросов. Он делает то же самое, что и HttpUtility, но находится вне пространства имен System.Web
Александру Алиу
3
Это неправильно, потому что он HtmlDecodes и не UrlEncode, как заданный вопрос. Даже HtmlEncode будет неправильным, поскольку кодировка HTML отличается от кодировки URL.
Мартин Браун