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


Если только дело с кодировкой url, я должен использовать EscapeUriString?

5 149

5 ответов:

вы используете EscapeUriString Если то, что вы убегаете, является URI, и EscapeDataString везде.

есть различия в том, как эти два кодируют строки.

подробнее здесь: http://blogs.msdn.com/b/yangxind/archive/2006/11/09/don-t-use-net-system-uri-unescapedatastring-in-url-decoding.aspx

я не нашел существующие ответы удовлетворительными, поэтому я решил копнуть немного глубже, чтобы решить эту проблему. Удивительно, но ответ очень прост:

нет никаких веских причин использовать Uri.EscapeUriString. Если вам нужно закодировать строку в процентах, всегда используйте Uri.EscapeDataString.

почему это? Согласно документация:

используйте метод EscapeUriString для подготовки строки UNESCAPED URI в качестве параметр конструктора Uri.

это действительно не имеет смысла. Согласно RFC 2396:

URI всегда находится в" экранированной " форме, так как экранирование или удаление завершенного URI может изменить его семантику.

в то время как цитируемый RFC был устаревшим RFC 3986 точка до сих пор стоит. Давайте проверим это, посмотрев на некоторые конкретные примеры:

  1. вы есть простой URI, как это:

    http://example.org/
    

    Uri.EscapeUriString не менять его.

  2. вы решили вручную отредактировать строку запроса без учета экранирования:

    http://example.org/?key=two words
    

    Uri.EscapeUriString будет (правильно) избежать пространства для вас:

    http://example.org/?key=two%20words
    
  3. вы решили вручную отредактировать строку запроса еще больше:

    http://example.org/?parameter=father&son
    

    однако, эта строка не изменяется Uri.EscapeUriString, так как он предполагает амперсанд означает начало другой пары ключ-значение. Это может быть или не быть то, что вы намеревались.

  4. вы решаете, что вы на самом деле хотите на father&son, так что вы исправить предыдущий URL-адрес вручную путем экранирования амперсанда:

    http://example.org/?parameter=father%26son
    

    однако, Uri.EscapeUriString также экранирует символ процента, что приводит к двойной кодировке:

    http://example.org/?parameter=father%2526son
    

как вы можете видеть, используя Uri.EscapeUriString по прямому назначению делает это невозможно использовать & как часть ключа или значения в строке запроса, а не как разделитель между несколькими парами ключ-значение.

это потому, что в ошибочной попытке сделать его пригодным для экранирования полных URI он игнорирует зарезервированные символы и только экранирует символы, которые не являются ни зарезервированными, ни незащищенными, что, кстати, противоречит документация. Таким образом, вы не в конечном итоге с чем-то вроде http%3A%2F%2Fexample.org%2F, но вы в конечном итоге с вопросами проиллюстрировано выше.


в конце концов, если ваш URI действителен, его не нужно экранировать, чтобы передать в качестве параметра в URI construtor, и если он недействителен, то вызов Uri.EscapeUriString не волшебное решение. На самом деле, это будет работать во многих, если не в большинстве случаев, но это ни в коем случае не надежно.

вы всегда должны создавать свои URL-адреса и строки запросов, собирая пары ключ-значение и процентное кодирование, а затем объединяя их с необходимыми сепараторы. Вы можете использовать Uri.EscapeDataString для этой цели, но не Uri.EscapeUriString, так как он не избежать зарезервированные символы, как упоминалось выше.

символы plus ( + ) могут многое рассказать о разнице между этими методами. В простом URI символ плюс означает "пробел". Подумайте о запросе Google для "happy cat":

https://www.google.com/?q=happy + кошка

это действительный URI (попробуйте), и EscapeUriString не изменять его.

Теперь рассмотрим запрос Google для " happy c++":

https://www.google.com/?q=happy+c++

это действительный URI (попробуйте), но он производит поиск "happy c", потому что два плюса интерпретируются как пробелы. Чтобы исправить это, мы можем передать "happy c++" в EscapeDataString и вуаля*:

https://www.google.com/?q=happy+c%2B%2B

*)закодированная строка данных на самом деле" happy%20c%2B%2B"; %20 является шестнадцатеричным для пространства символ, а %2B является шестнадцатеричным для символа плюс.

если вы используете UriBuilder Как вы должны быть, то вам понадобится только EscapeDataString чтобы правильно избежать некоторых компонентов всего URI. Ответ @ Livven на этот вопрос еще раз доказывает, что на самом деле нет причин использовать EscapeUriString.

комментарии источник четко разницу. Почему эта информация не передается через комментарии к XML-документации, для меня загадка.

EscapeUriString:

этот метод позволит избежать любой символ, который не является зарезервированным или неограниченный характер, включая знаки процента. Заметить что EscapeUriString также не будет избегать '#' знак.

EscapeDataString:

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

так разница в том, как они работают резерв символы. EscapeDataString ускользает от них; EscapeUriString нет.

по словам RFC, зарезервированных символов: :/?#[]@!$&'()*+,;=

для полноты картины, незащищенный символы буквенно-цифровые и -._~

оба метода экранируют символы, которые не являются ни зарезервированными, ни незащищенными.

Я не согласен с Генеральной понятие это EscapeUriString это зло. Я думаю, что метод, который ускользает только незаконно символы (например, пробелы), а не резерв символы-это полезно. Но у него есть причуда в том, как он обрабатывает % символ. Закодированные в процентах символы (% затем 2 шестигранника цифры) являются legal в URI. Я думаю EscapeUriString было бы гораздо полезнее, если бы он обнаружил этот шаблон и избежал кодирования % когда это сразу же продолжалось 2 шестнадцатеричными цифрами.

простой пример

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
*/