Як зробити UrlEncode без використання System.Web?


310

Я намагаюся написати клієнтську програму Windows, яка викликає веб-сайт для отримання даних. Щоб звести встановлення до мінімуму, я намагаюся використовувати лише dlls у профілі клієнта .NET Framework . Проблема полягає в тому, що мені потрібно UrlEncode деякі параметри, чи є простий спосіб це зробити без імпорту System.Web.dll, який не є частиною клієнтського файлу?


Чи можете ви показати, як ви здійснюєте дзвінок на веб-сайт? Можливо, там щось можна зробити.
Дарин Димитров

Як з цікавості ви називаєте веб-сайт для отримання даних без використання System.Web?
Патрік Макдональд

@Patrick, він, ймовірно, використовує 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()в будь-якому аспекті.


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), що насправді неможливо зробити послідовно. Детальну пояснення див. у цій відповіді .
Livven

Також космічний персонаж.
Waqas Shabbir

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(pre-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: // частину), в той час як EscapeUriString розуміє, які саме частини слід закодувати
Matthew Manela

1
Я бачу, тому в цьому випадку я, мабуть, хотів би EscapeDataString, оскільки я, можливо, захочу передати URL як параметр get. Я додаю URL-адресу в цьому випадку.
Мартін Браун

5
@MatthewManela Я впевнений, що ваш коментар Oct1
Маслоу

Не використовуйте Uri.EscapeUriString. Це не "розуміє", які частини слід закодувати, це просто помилкова спроба зробити щось (уникнути повних URI), що насправді неможливо послідовно зробити. Дивіться цю відповідь для детального пояснення.
Livven

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 не повинні містити зарезервовані символи '='та ';'.


приємний аналіз та розбивка тут, дуже корисний. якщо хтось має чи знає показники ефективності (порівнюючи всі три методи), які також було б приємно побачити
Shaun Wilson

Це хороший аналіз, і це означає, що ви не повинні використовувати Uri.EscapeUriString, тому що вийти з повних URI неможливо послідовно. Дивіться цю відповідь для детального пояснення.
Livven

16

У профілі клієнта є система користування профілем клієнта, клас System.Net.WebUtility, System.dll. Ось посилання 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

Клас WebUtility пропонує методи кодування та декодування URL-адрес під час обробки веб-запитів. Це робить те саме, що і HttpUtility, але це поза простором імен System.Web
Олександру Аліу

3
Це неправильно, оскільки він HtmlDecodes і не UrlEncode, як задане питання. Навіть HtmlEncode помиляється, оскільки кодування HTML відрізняється від кодування URL-адрес.
Мартін Браун
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.