Server.UrlEncode a HttpUtility.UrlEncode

177

Czy istnieje różnica między Server.UrlEncode i HttpUtility.UrlEncode?

Manu
źródło

Odpowiedzi:

133

HttpServerUtility.UrlEncodeużyje HttpUtility.UrlEncodewewnętrznie. Nie ma określonej różnicy. Powodem istnienia Server.UrlEncodejest kompatybilność z klasycznym ASP.

Mehrdad Afshari
źródło
3
Jeśli chodzi o to, co uciekło. Wewnętrznie wywołuje tę funkcję referenceource.microsoft.com/#System/net/System/Net/ ...
Jeff
Dla czytelników: proszę spojrzeć na odpowiedź Joela Mullera poniżej. To najskuteczniejszy sposób kodowania adresów URL: stackoverflow.com/a/603962/190476
Sudhanshu Mishra
264

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:

  • "" ==> "% 20"
  • „100% true” ==> „100 %% 20true” (ok, Twój adres URL jest teraz uszkodzony)
  • "test A.aspx # anchor B" ==> "test% 20A.aspx # anchor% 20B "
  • "test A.aspx? hmm # anchor B" ==> "test% 20A.aspx? hmm #anchor B " ( zwróć uwagę na różnicę w porównaniu z poprzednią sekwencją ucieczki! )

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 .

Eamon Nerbonne
źródło
4
I niestety to nadal nie działa podczas wykonywania żądań HTTP na niektórych serwerach internetowych - Uri.EscapeDataString () nie koduje „!” lub „'”, co różni się od sposobu działania większości implementacji funkcji escape () w przeglądarkach ...
Chris R. Donnelly,
6
! i „znaki nie powinny być kodowane; ale jeśli wymaga tego wadliwy serwer WWW, można to łatwo obejść. Unikaj funkcji ucieczki javascript - jest to z natury błędne (niemożliwe do wykonania w obie strony). Zobacz xkr.us/articles/javascript/encode-compare - ale w skrócie; zamiast tego możesz użyć encodeUriComponent (), który zachowuje się podobnie do EscapeDataString - koduje ciąg znaków w przewidywalny i odwracalny sposób, a także nie koduje! i 'znaków.
Eamon Nerbonne
2
To jest stare, ale pytanie trafiło na pierwszą stronę, więc ... Część ścieżki adresu URL jest częścią między domeną a? lub # w adresie URL.
Powerlord
2
@Tim: może być kilka ?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%. UrlPathEncodeMetoda jest zwykły borked i nigdy nie powinny być stosowane.
Eamon Nerbonne
1
Myślę, że moja odpowiedź na stackoverflow.com/a/13993486/237091 może rzucić trochę światła na zamierzone użycie UrlEncode / UrlPathEncode.
Scott Stafford,
60

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:

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 -._~

Werdykt

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.EncodeIllegalCharactersoraz Url.Decodemetod 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}");
Todd Menier
źródło
2
To jest genialne!
Jorge Aguirre
1
Świetna robota, weryfikacja sugerowanego rozwiązania na nowoczesnym frameworku .net.
Neowizard
Należy wspomnieć, że istnieją pewne różnice między WebUtility i HttpUtility . WebUtility używa wielkich liter, a HttpUtility używa małych liter dla jednostek hexa. Ponadto HttpUtility nie został uwzględniony w starszych wersjach podzbioru „Client Profile” .NET Framework. WebUtility jest dostępne z .NET Framework 4.0.
tibx
28

Pamiętaj, że prawdopodobnie nie powinieneś używać żadnej z tych metod. Biblioteka Microsoft Anti-Cross Site Scripting Library zawiera zamienniki HttpUtility.UrlEncodei HttpUtility.HtmlEncodesą zarówno bardziej zgodne ze standardami, jak i bezpieczniejsze. Jako bonus otrzymujesz również JavaScriptEncodemetodę.

Joel Mueller
źródło
Po przeczytaniu dokumentacji i często zadawanych pytań pod podanym linkiem uważam, że ta odpowiedź jest najlepszym i najbezpieczniejszym sposobem kodowania danych! Wielkie dzięki za udostępnienie tego!
Sudhanshu Mishra
Link już nie działa. Jakie są metody wymiany?
Edward Brey
@EdwardBrey To jest najnowsza wersja biblioteki skryptów Anti-Cross: microsoft.com/en-au/download/details.aspx?id=28589
Sudhanshu Mishra
11

Server.UrlEncode () zapewnia wsteczną zgodność z klasyczną ASP,

Server.UrlEncode(str);

Jest równa:

HttpUtility.UrlEncode(str, Response.ContentEncoding);
CMS
źródło
5

To samo Server.UrlEncode()dzwoniHttpUtility.UrlEncode()

andleer
źródło