Якщо ви маєте справу лише з кодуванням url, я повинен використовувати EscapeUriString ?
Якщо ви маєте справу лише з кодуванням url, я повинен використовувати EscapeUriString ?
Відповіді:
Використовуйте EscapeDataString
завжди (для отримання додаткової інформації про те, чому дивіться відповідь Ліввена нижче)
Редагувати : видалено мертве посилання на те, як вони відрізняються при кодуванні
URLEncode
занадто).
Я не вважав наявні відповіді задовільними, тому вирішив заглибитись трохи глибше, щоб вирішити це питання. Дивно, але відповідь дуже проста:
Немає (майже *) поважних причин ніколи не використовувати Uri.EscapeUriString
. Якщо вам потрібно кодувати рядок у відсотках, завжди використовуйте Uri.EscapeDataString
.
* Дивіться останній абзац щодо дійсного випадку використання.
Чому це? Відповідно до документації :
Використовуйте метод EscapeUriString, щоб підготувати необмежену рядок URI, щоб бути параметром для конструктора Uri.
Це насправді не має сенсу. Відповідно до RFC 2396 :
URI завжди знаходиться у "уникнутому" вигляді, оскільки втеча або скасування на завершений URI може змінити його семантику.
Поки RFC 3986 цитується, що котирується, застаріла справа. Давайте перевіримо це, переглянувши кілька конкретних прикладів:
У вас простий URI, такий:
http://example.org/
Uri.EscapeUriString
не змінить це.
Ви вирішите вручну відредагувати рядок запиту, не враховуючи можливі можливості втечі:
http://example.org/?key=two words
Uri.EscapeUriString
(правильно) уникне місця для вас:
http://example.org/?key=two%20words
Ви вирішили ще більше відредагувати рядок запиту:
http://example.org/?parameter=father&son
Однак цей рядок не змінено Uri.EscapeUriString
, оскільки він передбачає, що амперсанд означає початок іншої пари ключ-значення. Це може бути або не бути тим, що ви задумали.
Ви вирішили, що хочете, щоб цей key
параметр був father&son
, тому ви виправляєте попередню URL-адресу вручну, уникаючи амперсанд
http://example.org/?parameter=father%26son
Однак Uri.EscapeUriString
уникне і відсотковий символ, що призведе до подвійного кодування:
http://example.org/?parameter=father%2526son
Як бачите, використання Uri.EscapeUriString
за призначенням унеможливлює використання &
як частини ключа або значення в рядку запиту, а не як роздільник між кількома парами ключ-значення.
Це відбувається тому, що, намагаючись зробити його придатним для виходу з повних URI, він ігнорує зарезервовані символи та уникає лише символів, які не є ні зарезервованими, ні незарезервованими, що, BTW, суперечить документації . Таким чином ви не закінчите щось подібне http%3A%2F%2Fexample.org%2F
, але все-таки вирішите проблеми, проілюстровані вище.
Врешті-решт, якщо ваш URI дійсний, його не потрібно уникати, щоб передати його як параметр конститутору Uri, а якщо він недійсний, то і виклик Uri.EscapeUriString
не є магічним рішенням. Насправді це буде працювати у багатьох, якщо не в більшості випадків, але це аж ніяк не є надійним.
Ви завжди повинні будувати свої URL-адреси та рядки запитів, збираючи пари ключових значень і відсоткове кодування, а потім з'єднуючи їх з необхідними роздільниками. Ви можете використовувати Uri.EscapeDataString
для цієї мети, але ні Uri.EscapeUriString
, оскільки це не уникає зарезервованих символів, як зазначено вище.
Тільки якщо ви не можете цього зробити, наприклад, працюючи з наданими користувачем URI, має сенс використовувати Uri.EscapeUriString
в крайньому випадку. Але застосовуються раніше застереження - якщо URI, що надається користувачем, неоднозначний, результати можуть бути не бажаними.
encodeURI
/ Uri.EscapeUriString
не потрібно так часто, як encodeURIComponent
/ Uri.EscapeDataString
(оскільки коли ви здійснюєте деалінгування зі сліпими URL-адресами, які повинні використовуватися в урі-контексті), але це не означає, що воно не має свого місця.
Символи плюс (+) можуть виявити багато про різницю між цими методами. У простому URI символ плюс означає "пробіл". Розглянемо запит Google щодо "щасливої кішки":
Це дійсний URI (спробуйте його), і EscapeUriString
він не змінює його.
Тепер розглянемо запит Google на "happy c ++":
Це дійсний URI (спробуйте), але він створює пошук "happy c", оскільки два плюси інтерпретуються як пробіли. Щоб виправити це, ми можемо передати "happy c ++" до EscapeDataString
і voila * :
*) Рядок закодованих даних насправді "щасливий% 20c% 2B% 2B"; % 20 - це шістнадцятковий символ для пробілу, а% 2B - шестнадцятковий для символу плюс.
Якщо ви використовуєте UriBuilder
як слід, тоді вам потрібно буде лише EscapeDataString
належним чином уникнути деяких компонентів всього вашого URI. @ Відповідь Ліввена на це запитання ще більше доводить, що дійсно немає підстав для використання EscapeUriString
.
"https://www.google.com/?q=happy c++"
. Схоже, мені потрібно вручну розділити на "?", Чи є кращий спосіб?
EscapeDataString
. Якщо вказана вами URL-адреса є фактичною URL-адресою, то так, ви хочете просто розділити ?
.
Коментарі в джерелі вирішують різницю чітко. Чому ця інформація не передається через коментарі документації XML, для мене загадка.
EscapeUriString:
Цей метод дозволить уникнути будь-якого символу, який не є зарезервованим або незарезервованим символом, включаючи знаки відсотків. Зауважте, що EscapeUriString також не уникатиме знаку "#".
EscapeDataString:
Цей метод дозволить уникнути будь-якого персонажа, який не є беззастережним символом, включаючи знаки відсотків.
Тому різниця полягає в тому, як вони поводяться із зарезервованими символами. EscapeDataString
тікає від них; EscapeUriString
не.
За даними RFC , зарезервовані символи::/?#[]@!$&'()*+,;=
Для повноти беззастережні символи буквено-цифрові та -._~
Обидва методи уникають символів, які не є ні зарезервованими, ні незарезервованими.
Я не згоден із загальним поняттям, що EscapeUriString
це зло. Я думаю, що метод, який дозволяє уникати лише незаконних символів (наприклад, пробіли) і не зарезервовані символи, є корисним. Але у нього є химерність у тому, як він поводиться з %
персонажем. Персонально закодовані символи ( %
далі 2 шістнадцяткових цифр) є законними в URI. Думаю, EscapeUriString
було б набагато корисніше, якби він виявив цю закономірність і уникнув кодування, %
коли з неї негайно продовжуються дві шістнадцяткові цифри.
Простий приклад
var data = "example.com/abc?DEF=あいう\x20えお";
Console.WriteLine(Uri.EscapeUriString(data));
Console.WriteLine(Uri.EscapeDataString(data));
Console.WriteLine(System.Net.WebUtility.UrlEncode(data));
Console.WriteLine(System.Web.HttpUtility.UrlEncode(data));
/*
=>
example.com/abc?DEF=%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A
example.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A
example.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86+%E3%81%88%E3%81%8A
example.com%2fabc%3fDEF%3d%e3%81%82%e3%81%84%e3%81%86+%e3%81%88%e3%81%8a
*/
Uri.EscapeDataString()
, як пояснено у відповіді @ Livven. При інших підходах система просто не має достатньо інформації для створення запланованого результату для кожного можливого введення.