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 представляется предпочтительным. Но так ли это? Я сделал некоторый анализ, чтобы понять различия, и вот что я придумал:
WebUtility.UrlEncode
кодирует пространство как+
;Uri.EscapeDataString
кодирует это как%20
,Uri.EscapeDataString
процентов кодирует!
,(
,)
, а также*
;WebUtility.UrlEncode
не.WebUtility.UrlEncode
процентов кодирует~
;Uri.EscapeDataString
не.Uri.EscapeDataString
бросаетUriFormatException
на строках длиннее 65 520 символов;WebUtility.UrlEncode
не. ( Более распространенная проблема, чем вы можете подумать, особенно когда речь идет о данных формы в кодировке URL.)Uri.EscapeDataString
бросаетUriFormatException
на высоких суррогатных персонажей;WebUtility.UrlEncode
не. (Это UTF-16, вероятно, гораздо реже.)
В целях кодирования 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);