Server.UrlEncode против HttpUtility.UrlEncode

Ответы:

133

HttpServerUtility.UrlEncodeбудет использовать HttpUtility.UrlEncodeвнутри. Особой разницы нет. Причиной существования Server.UrlEncodeявляется совместимость с классическим ASP.

Мехрдад Афшари
источник
3
Что касается того, что сбежит. Внутренне он вызывает эту функцию Referenceource.microsoft.com/#System/net/System/Net/…
Джефф
Для читателей: Пожалуйста, посмотрите ответ Джоэля Мюллера ниже. Это наиболее эффективный способ кодирования URL: stackoverflow.com/a/603962/190476
Судханшу Мишра,
264

Раньше у меня были серьезные головные боли с этими методами, я рекомендую вам избегать любого варианта UrlEncode, и вместо этого использоватьUri.EscapeDataString - по крайней мере, тот, который имеет понятное поведение.

Посмотрим...

HttpUtility.UrlEncode(" ") == "+" //breaks ASP.NET when used in paths, non-
                                  //standard, undocumented.
Uri.EscapeUriString("a?b=e") == "a?b=e" // makes sense, but rarely what you
                                        // want, since you still need to
                                        // escape special characters yourself

Но мой личный фаворит должен быть HttpUtility.UrlPathEncode - эта вещь действительно непостижима. Он кодирует:

  • "" ==> "% 20"
  • "100% true" ==> "100 %% 20true" (хорошо, ваш URL сейчас не работает)
  • "test A.aspx # anchor B" ==> "test% 20A.aspx # anchor% 20B "
  • "test A.aspx? hmm # anchor B" ==> "test% 20A.aspx? hmm #anchor B " ( обратите внимание на разницу с предыдущей escape-последовательностью! )

Он также имеет прекрасную документацию MSDN «Кодирует часть пути строки URL для надежной передачи HTTP с веб-сервера клиенту». - фактически не объясняя, что он делает. Вы с меньшей вероятностью выстрелите себе в ногу из узи ...

Короче говоря, придерживайтесь Uri.EscapeDataString .

Имон Нербонн
источник
4
И, к сожалению, это не работает при выполнении HTTP-запросов к некоторым веб-серверам - Uri.EscapeDataString () не кодирует «!» или «», что отличается от того, как работает большинство браузерных реализаций escape () ...
Крис Р. Доннелли,
6
! и символы не должны быть закодированы; но если этого требует неисправный веб-сервер, это легко обойти. Избегайте функции побега javascript - она ​​по своей сути глючная (например, туда и обратно невозможно). См. Xkr.us/articles/javascript/encode-compare - но вкратце; вместо этого вы можете использовать encodeUriComponent (), который работает аналогично EscapeDataString - он предсказуемо и обратимо кодирует строку, а также не кодирует! и 'персонажи.
Имон Нербонн
2
Это старый, но вопрос был перенесен на первую страницу, так что .... Часть пути строки URL - это часть между доменом и? или # в URL.
Powerlord
2
@Tim: их может быть несколько, ?и кто скажет, какие из них должны быть закодированы, а какие служат разделителями? Что касается пространства: в обоих случаях пространство находится в хэше, поэтому наличие или отсутствие фрагмента запроса не должно иметь значения. И, наконец, непростительно испортить Uri, как во втором примере, содержащем%. Этот UrlPathEncodeметод прост и не должен использоваться.
Имон Нербонн
1
Я думаю, что мой ответ на stackoverflow.com/a/13993486/237091 может пролить немного света на предполагаемое использование UrlEncode / UrlPathEncode.
Скотт Стаффорд,
60

Перенесемся вперед почти 9 лет с тех пор, как это было впервые задано, и в мире .NET Core и .NET Standard наиболее распространенными вариантами кодирования URL, по- видимому, являются WebUtility.UrlEncode (under System.Net) и Uri.EscapeDataString . Судя по наиболее популярному ответу здесь и в других местах, Uri.EscapeDataString представляется предпочтительным. Но так ли это? Я сделал некоторый анализ, чтобы понять различия, и вот что я придумал:

В целях кодирования URL символы попадают в одну из 3 категорий: безрезультатно (допустимо в URL); зарезервировано (законно, но имеет особое значение, так что вы можете закодировать его); и все остальное (всегда должно быть закодировано).

По данным РФЦ , зарезервированные символы::/?#[]@!$&'()*+,;=

И незарезервированные символы являются буквенно-цифровыми и -._~

Вердикт

Uri.EscapeDataString четко определяет свою миссию:% -кодировать все зарезервированные и недопустимые символы. WebUtility.UrlEncode более неоднозначен как в определении, так и в реализации. Как ни странно, он кодирует некоторые зарезервированные символы, но не другие (почему скобки, а не скобки ??), и, что еще более странно, он кодирует этот невинно незарезервированный ~символ.

Поэтому я согласен с популярным советом - используйте Uri.EscapeDataString, когда это возможно, и понимаю, что зарезервированные символы любят /и ?будут закодированы. Если вам нужно иметь дело с потенциально большими строками, особенно с содержимым формы в кодировке URL, вам нужно либо воспользоваться WebUtility.UrlEncode и принять его причуды, либо иным образом обойти проблему.


EDIT: Я пытался исправить все из причуд , упомянутых выше в Flurl через Url.Encode, Url.EncodeIllegalCharactersи Url.Decodeстатические методы. Они находятся в основном пакете (который крошечный и не включает в себя все HTTP), или можете свободно копировать их из исходного кода. Я приветствую любые ваши комментарии / отзывы.


Вот код, который я использовал, чтобы узнать, какие символы кодируются по-разному:

var diffs =
    from i in Enumerable.Range(0, char.MaxValue + 1)
    let c = (char)i
    where !char.IsHighSurrogate(c)
    let diff = new {
        Original = c,
        UrlEncode = WebUtility.UrlEncode(c.ToString()),
        EscapeDataString = Uri.EscapeDataString(c.ToString()),
    }
    where diff.UrlEncode != diff.EscapeDataString
    select diff;

foreach (var diff in diffs)
    Console.WriteLine($"{diff.Original}\t{diff.UrlEncode}\t{diff.EscapeDataString}");
Тодд менье
источник
2
Это великолепно!
Хорхе Агирре
1
Отличная работа по проверке предлагаемого решения на современной .net Framework.
Neowizard
Следует отметить, что между WebUtility и HttpUtility существуют некоторые различия . WebUtility использует прописные буквы, а HttpUtility использует строчные для шестнадцатеричных сущностей. Кроме того, HttpUtility не была включена в старые версии подмножества .NET Framework «Профиль клиента». Веб-утилита доступна из .NET Framework 4.0.
tibx
28

Имейте в виду, что вам, вероятно, не следует использовать ни один из этих методов. От Microsoft Anti-Cross Site Scripting Library включает в себя замену для HttpUtility.UrlEncodeи HttpUtility.HtmlEncodeчто оба являются более соответствующими стандартами, и более безопасным. В качестве бонуса вы также получаете JavaScriptEncodeметод.

Джоэл Мюллер
источник
После прочтения документации и FAQ по предоставленной ссылке, я считаю, что этот ответ - лучший и самый безопасный способ кодирования данных! Спасибо огромное за то, что поделились этим!
Судханшу Мишра
Ссылка больше не работает. Какие методы замены?
Эдвард Брей
@EdwardBrey Это последняя версия библиотеки сценариев сайта Anti-Cross: microsoft.com/en-au/download/details.aspx?id=28589
Судханшу Мишра,
11

Server.UrlEncode () предназначен для обеспечения обратной совместимости с классическим ASP,

Server.UrlEncode(str);

Эквивалентно:

HttpUtility.UrlEncode(str, Response.ContentEncoding);
CMS
источник
5

То же самое, Server.UrlEncode()звонкиHttpUtility.UrlEncode()

andleer
источник