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

Есть ли разница между Server.UrlEncode и HttpUtility.UrlEncode?

6 ответов

Решение

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

У меня были значительные головные боли с этими методами раньше, я рекомендую вам избегать любого варианта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.

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

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

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

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

Вердикт

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

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


РЕДАКТИРОВАТЬ: Я пытался исправить ВСЕ из причуд, упомянутых выше в 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}");

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

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

Server.UrlEncode(str);

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

HttpUtility.UrlEncode(str, Response.ContentEncoding);

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

Другие вопросы по тегам