Jeśli tylko zajmujesz się kodowaniem adresów URL, powinienem użyć EscapeUriString ?
Jeśli tylko zajmujesz się kodowaniem adresów URL, powinienem użyć EscapeUriString ?
Odpowiedzi:
Używaj EscapeDataStringzawsze (więcej informacji na temat przyczyny znajduje się poniżej w odpowiedzi Livven )
Edycja : usunięto martwy link do różnic między kodowaniem
URLEncode).
Nie uznałem istniejących odpowiedzi za zadowalające, więc postanowiłem głębiej zbadać ten problem. Co zaskakujące, odpowiedź jest bardzo prosta:
Nie ma (prawie *) żadnego ważnego powodu, aby kiedykolwiek używać Uri.EscapeUriString. Jeśli potrzebujesz procentowo zakodować ciąg, zawsze używaj Uri.EscapeDataString.
* Patrz ostatni akapit dla ważnego przypadku użycia.
Dlaczego to? Zgodnie z dokumentacją :
Użyj metody EscapeUriString, aby przygotować nieskalowany ciąg URI, który będzie parametrem dla konstruktora Uri.
To naprawdę nie ma sensu. Zgodnie z RFC 2396 :
Identyfikator URI jest zawsze w formie „ucieczki”, ponieważ ucieczka lub odblokowanie ukończonego URI może zmienić jego semantykę.
Chociaż cytowany RFC został zdezaktualizowany przez RFC 3986 , kwestia nadal jest ważna. Sprawdźmy to, patrząc na konkretne przykłady:
Masz prosty identyfikator URI, taki jak ten:
http://example.org/
Uri.EscapeUriString nie zmieni tego.
Zdecydujesz się ręcznie edytować ciąg zapytania bez uwzględnienia zmiany znaczenia:
http://example.org/?key=two words
Uri.EscapeUriString (poprawnie) wydostanie się z miejsca dla ciebie:
http://example.org/?key=two%20wordsZdecydujesz się ręcznie edytować ciąg zapytania jeszcze dalej:
http://example.org/?parameter=father&son
Jednak ten ciąg nie jest zmieniany przez Uri.EscapeUriString, ponieważ zakłada, że ampersand oznacza początek innej pary klucz-wartość. To może, ale nie musi być to, co zamierzałeś.
Decydujesz, że tak naprawdę chcesz, aby keyparametr był father&son, więc naprawiasz poprzedni adres URL ręcznie, usuwając znak ampersand:
http://example.org/?parameter=father%26son
Jednak Uri.EscapeUriStringucieknie również od znaku procentu, co prowadzi do podwójnego kodowania:
http://example.org/?parameter=father%2526sonJak widać, użycie Uri.EscapeUriStringzgodnie z przeznaczeniem uniemożliwia użycie &jako części klucza lub wartości w ciągu zapytania zamiast jako separatora między wieloma parami klucz-wartość.
Wynika to z tego, że próbując uczynić go odpowiednim do ucieczki pełnych identyfikatorów URI, ignoruje znaki zarezerwowane i unika tylko znaków, które nie są zastrzeżone ani niezarezerwowane, co BTW jest sprzeczne z dokumentacją . W ten sposób nie kończy się coś takiego http%3A%2F%2Fexample.org%2F, ale kończy się to przedstawionymi powyżej problemami.
Ostatecznie, jeśli twój identyfikator URI jest prawidłowy, nie musi być poprzedzany znakiem ucieczki, aby mógł zostać przekazany jako parametr do konstruktora Uri, a jeśli nie jest prawidłowy, wywołanie również Uri.EscapeUriStringnie jest magicznym rozwiązaniem. W rzeczywistości będzie działać w wielu, jeśli nie w większości przypadków, ale w żadnym wypadku nie jest niezawodny.
Zawsze należy konstruować adresy URL i ciągi zapytań, gromadząc pary klucz-wartość i kodowanie procentowe, a następnie łącząc je z niezbędnymi separatorami. Możesz użyć Uri.EscapeDataStringdo tego celu, ale nie Uri.EscapeUriString, ponieważ nie ucieka on od zarezerwowanych znaków, jak wspomniano powyżej.
Tylko wtedy, gdy nie możesz tego zrobić, np. W przypadku identyfikatorów URI podanych przez użytkownika, ma sens zastosowanie Uri.EscapeUriStringw ostateczności. Obowiązują jednak wspomniane wcześniej zastrzeżenia - jeśli podany przez użytkownika identyfikator URI jest niejednoznaczny, wyniki mogą być niepożądane.
encodeURI/ Uri.EscapeUriStringnie jest potrzebny tak często jak encodeURIComponent/ Uri.EscapeDataString(od kiedy masz do czynienia z ślepymi adresami URL, które muszą być używane w kontekście URI), ale to nie znaczy, że nie ma swojego miejsca.
Znaki plus (+) mogą wiele powiedzieć o różnicy między tymi metodami. W prostym URI znak plus oznacza „spację”. Rozważ zapytanie do Google o „szczęśliwego kota”:
To prawidłowy identyfikator URI (spróbuj) i EscapeUriStringnie będzie go modyfikować.
Teraz rozważ zapytanie Google o „happy c ++”:
To jest poprawny URI (spróbuj), ale powoduje wyszukiwanie „szczęśliwego c”, ponieważ dwie plusy są interpretowane jako spacje. Aby to naprawić, możemy przekazać „happy c ++” do EscapeDataStringi voila * :
*) Zakodowany ciąg danych to tak naprawdę „happy% 20c% 2B% 2B”; % 20 to hex dla znaku spacji, a% 2B to hex dla znaku plus.
Jeśli używasz tego, UriBuilderco powinieneś, musisz EscapeDataStringwłaściwie uciec tylko niektórych składników całego identyfikatora URI. Odpowiedź @ Livven na to pytanie dalej dowodzi, że tak naprawdę nie ma powodu, aby z tego korzystać EscapeUriString.
"https://www.google.com/?q=happy c++". Wygląda na to, że muszę ręcznie podzielić na „?”, Czy jest lepszy sposób?
EscapeDataString. Jeśli podany adres URL jest rzeczywistym adresem URL, to tak, po prostu chcesz się podzielić ?.
Komentarze w źródle wyraźnie odnoszą się do różnicy. Dlaczego te informacje nie są przekazywane za pośrednictwem komentarzy do dokumentacji XML, jest dla mnie zagadką.
EscapeUriString:
Ta metoda pozwoli uniknąć dowolnego znaku, który nie jest znakiem zastrzeżonym lub niezarezerwowanym, w tym znaków procentu. Pamiętaj, że EscapeUriString również nie uniknie znaku „#”.
EscapeDataString:
Ta metoda pozwoli uniknąć dowolnego znaku, który nie jest znakiem bez zastrzeżeń, w tym znaków procentu.
Różnica polega na tym, jak radzą sobie z zastrzeżonymi znakami. EscapeDataStringucieka im; EscapeUriStringnie.
Zgodnie z RFC zarezerwowanymi znakami są::/?#[]@!$&'()*+,;=
Dla kompletności, niezarezerwowane znaki są alfanumeryczne i -._~
Obie metody unikają znaków, które nie są ani zarezerwowane, ani zastrzeżone.
Nie zgadzam się z ogólnym pojęciem, które EscapeUriStringjest złe. Myślę, że metoda, która pozwala na uniknięcie tylko niedozwolonych znaków (takich jak spacje) i niezastrzeżonych znaków, jest przydatna. Ale ma dziwactwo w tym, jak radzi sobie z %postacią. Znaki zakodowane w procentach ( %po których następują 2 cyfry szesnastkowe) są poprawne w URI. Myślę, że EscapeUriStringbyłoby znacznie bardziej przydatne, gdyby wykrył ten wzorzec i uniknął kodowania, %gdy natychmiast poprzedzają go 2 cyfry szesnastkowe.
Prosty przykład
var data = "example.com/abc?DEF=あいう\x20えお";
Console.WriteLine(Uri.EscapeUriString(data));
Console.WriteLine(Uri.EscapeDataString(data));
Console.WriteLine(System.Net.WebUtility.UrlEncode(data));
Console.WriteLine(System.Web.HttpUtility.UrlEncode(data));
/*
=>
example.com/abc?DEF=%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A
example.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A
example.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86+%E3%81%88%E3%81%8A
example.com%2fabc%3fDEF%3d%e3%81%82%e3%81%84%e3%81%86+%e3%81%88%e3%81%8a
*/
Uri.EscapeDataString(), jak wyjaśniono w odpowiedzi @ Livven. W przypadku innych podejść system po prostu nie ma wystarczających informacji, aby uzyskać zamierzony wynik dla każdego możliwego wkładu.