Odpowiedzi:
HttpServerUtility.UrlEncode
użyje HttpUtility.UrlEncode
wewnętrznie. Nie ma określonej różnicy. Powodem istnienia Server.UrlEncode
jest kompatybilność z klasycznym ASP.
Miałem już wcześniej spore bóle głowy z tymi metodami, radzę unikać jakichkolwiek ich wariantów UrlEncode
, a zamiast tego stosowaćUri.EscapeDataString
- przynajmniej ten ma zrozumiałe zachowanie.
Zobaczmy...
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
Ale moim osobistym faworytem musi być HttpUtility.UrlPathEncode - ta rzecz jest naprawdę niezrozumiała. Koduje:
Zawiera również piękną, specyficzną dokumentację MSDN „Koduje fragment ścieżki adresu URL w celu zapewnienia niezawodnej transmisji HTTP z serwera sieci Web do klienta”. - bez faktycznego wyjaśniania, co robi. Rzadziej strzelisz sobie w stopę z Uzi ...
Krótko mówiąc, trzymaj się Uri.EscapeDataString .
?
i kto powie, które mają zostać zakodowane, a które służą jako separatory? Co do przestrzeni: w obu przypadkach spacja jest w skrócie, więc obecność lub brak fragmentu zapytania nie powinno mieć znaczenia. I wreszcie, niewybaczalne jest uszkodzenie Uri, jak w drugim przykładzie zawierającym%. UrlPathEncode
Metoda jest zwykły borked i nigdy nie powinny być stosowane.
Przewiń do przodu prawie 9 lat od pierwszego pytania, aw świecie .NET Core i .NET Standard wydaje się, że najczęstszymi opcjami kodowania adresów URL są WebUtility.UrlEncode (under System.Net
) i Uri.EscapeDataString . Sądząc po najpopularniejszej odpowiedzi tutaj i gdzie indziej, Uri.EscapeDataString wydaje się być lepszym rozwiązaniem. Ale czy tak jest? Przeprowadziłem analizę, aby zrozumieć różnice i oto, co wymyśliłem:
WebUtility.UrlEncode
koduje przestrzeń jako +
; Uri.EscapeDataString
koduje go jako %20
.Uri.EscapeDataString
Procenty koduje !
, (
, )
i *
; WebUtility.UrlEncode
nie.WebUtility.UrlEncode
kody procentowe ~
; Uri.EscapeDataString
nie.Uri.EscapeDataString
rzuca a UriFormatException
na ciągi dłuższe niż 65 520 znaków; WebUtility.UrlEncode
nie. ( Częstszy problem, niż mogłoby się wydawać, szczególnie w przypadku danych formularzy zakodowanych w adresach URL ).Uri.EscapeDataString
rzuca a UriFormatException
na wysokie znaki zastępcze ; WebUtility.UrlEncode
nie. (To rzecz UTF-16, prawdopodobnie dużo mniej powszechna).Do celów kodowania adresów URL znaki mieszczą się w jednej z 3 kategorii: niezarezerwowane (legalne w adresie URL); zastrzeżone (prawny, ale ma specjalne znaczenie, więc może chcesz go zakodować); i wszystko inne (zawsze musi być zakodowane).
Zgodnie z RFC , zastrzeżone znaki to::/?#[]@!$&'()*+,;=
Niezastrzeżone znaki to alfanumeryczne i -._~
Uri.EscapeDataString jasno określa swoją misję:% -koduj wszystkie zastrzeżone i nielegalne znaki. WebUtility.UrlEncode jest bardziej niejednoznaczny zarówno pod względem definicji, jak i implementacji. Co dziwne, koduje niektóre zastrzeżone znaki, ale nie inne (dlaczego nawiasy, a nie nawiasy ??), a co dziwniejsze, koduje ten niewinnie niezastrzeżony ~
znak.
Dlatego zgadzam się z popularną radą - używaj Uri.EscapeDataString, gdy to możliwe, i rozumiem, że zastrzeżone znaki, takie jak /
i ?
zostaną zakodowane. Jeśli musisz poradzić sobie z potencjalnie dużymi ciągami, szczególnie z treścią formularza zakodowaną w adresie URL, musisz albo wrócić do WebUtility.UrlEncode i zaakceptować jego dziwactwa, albo w inny sposób obejść problem.
EDIT: Mam próbował naprawić WSZYSTKIE dziwactw wymienionych powyżej w Flurl pośrednictwem Url.Encode
, Url.EncodeIllegalCharacters
oraz Url.Decode
metod statycznych. Znajdują się one w podstawowym pakiecie (który jest mały i nie zawiera wszystkich elementów HTTP) lub możesz je zgrać ze źródła. Czekam na wszelkie komentarze i opinie na ich temat.
Oto kod, którego użyłem do odkrycia, które znaki są zakodowane inaczej:
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}");
Pamiętaj, że prawdopodobnie nie powinieneś używać żadnej z tych metod. Biblioteka Microsoft Anti-Cross Site Scripting Library zawiera zamienniki HttpUtility.UrlEncode
i HttpUtility.HtmlEncode
są zarówno bardziej zgodne ze standardami, jak i bezpieczniejsze. Jako bonus otrzymujesz również JavaScriptEncode
metodę.