Se dovessi occuparmi solo della codifica degli URL, dovrei usare EscapeUriString ?
Se dovessi occuparmi solo della codifica degli URL, dovrei usare EscapeUriString ?
Risposte:
Usa EscapeDataString
sempre (per maggiori informazioni sul perché, vedi la risposta di Livven di seguito)
Modifica : rimosso il link morto su come i due differiscono nella codifica
URLEncode
anche con ).
Non ho trovato soddisfacenti le risposte esistenti, quindi ho deciso di scavare un po 'più a fondo per risolvere il problema. Sorprendentemente, la risposta è molto semplice:
Non c'è (quasi *) alcun motivo valido per usarlo mai Uri.EscapeUriString
. Se è necessario codificare in percentuale una stringa, utilizzare sempre Uri.EscapeDataString
.
* Vedi l'ultimo paragrafo per un caso d'uso valido.
Perchè è questo? Secondo la documentazione :
Utilizzare il metodo EscapeUriString per preparare una stringa URI senza escape per essere un parametro per il costruttore Uri.
Questo non ha davvero senso. Secondo RFC 2396 :
Un URI è sempre in una forma di "escape", poiché l'escape o l'escaping di un URI completato potrebbe modificarne la semantica.
Mentre il RFC citato è stato superato da RFC 3986 , il punto è ancora valido. Verifichiamolo guardando alcuni esempi concreti:
Hai un URI semplice, come questo:
http://example.org/
Uri.EscapeUriString
non lo cambierà.
Decidi di modificare manualmente la stringa di query senza considerare l'escaping:
http://example.org/?key=two words
Uri.EscapeUriString
sfuggirà (correttamente) allo spazio per te:
http://example.org/?key=two%20words
Decidi di modificare ulteriormente manualmente la stringa di query:
http://example.org/?parameter=father&son
Tuttavia, questa stringa non viene modificata da Uri.EscapeUriString
, poiché presuppone che la e commerciale significhi l'inizio di un'altra coppia chiave-valore. Questo può o meno essere quello che volevi.
Decidi di voler effettivamente essere il key
parametro father&son
, quindi correggi manualmente l'URL precedente sfuggendo alla e commerciale:
http://example.org/?parameter=father%26son
Tuttavia, Uri.EscapeUriString
sfuggirà anche al carattere percentuale, portando a una doppia codifica:
http://example.org/?parameter=father%2526son
Come puoi vedere, l'uso Uri.EscapeUriString
per lo scopo previsto rende impossibile l'utilizzo &
come parte di una chiave o valore in una stringa di query anziché come separatore tra più coppie chiave-valore.
Questo perché, nel tentativo di renderlo adatto alla fuga di URI completi, ignora i caratteri riservati e sfugge solo ai caratteri che non sono né riservati né senza riserve, il che, a proposito, è contrario alla documentazione . In questo modo non si finisce con qualcosa del generehttp%3A%2F%2Fexample.org%2F
, ma si finisce con i problemi illustrati sopra.
Alla fine, se l'URI è valido, non è necessario eseguirne l'escaping per passare come parametro al costruttore Uri e, se non è valido, chiamare Uri.EscapeUriString
non è una soluzione magica. In realtà, funzionerà in molti, se non nella maggior parte dei casi, ma non è affatto affidabile.
Dovresti sempre costruire i tuoi URL e stringhe di query raccogliendo le coppie chiave-valore e la codifica percentuale e concatenandole con i separatori necessari. È possibile utilizzare Uri.EscapeDataString
per questo scopo, ma non Uri.EscapeUriString
, poiché non sfugge ai caratteri riservati, come menzionato sopra.
Solo se non puoi farlo, ad es. Quando hai a che fare con URI forniti dagli utenti, ha senso usarlo Uri.EscapeUriString
come ultima risorsa. Ma si applicano le avvertenze menzionate in precedenza: se l'URI fornito dall'utente è ambiguo, i risultati potrebbero non essere desiderabili.
encodeURI
/ Uri.EscapeUriString
non è necessario con la stessa frequenza di ( encodeURIComponent
/ Uri.EscapeDataString
da quando stai cantando con url ciechi che devono essere usati in un contesto uri), ma ciò non significa che non abbia il suo posto.
I caratteri più (+) possono rivelare molto sulla differenza tra questi metodi. In un semplice URI, il carattere più significa "spazio". Valuta la possibilità di richiedere a Google "gatto felice":
È un URI valido (provalo) e EscapeUriString
non lo modificherà.
Ora considera di interrogare Google per "happy c ++":
È un URI valido (provalo), ma produce una ricerca di "c felice", perché i due vantaggi sono interpretati come spazi. Per risolvere il problema, possiamo passare "happy c ++" a EscapeDataString
e voilà * :
*) La stringa di dati codificata è in realtà "happy% 20c% 2B% 2B"; % 20 è esadecimale per il carattere spazio e% 2B è esadecimale per il carattere più.
Se stai usando UriBuilder
come dovresti, dovrai solo EscapeDataString
sfuggire correttamente ad alcuni dei componenti dell'intero URI. La risposta di @ Livven a questa domanda dimostra ulteriormente che non c'è davvero alcun motivo per usare EscapeUriString
.
"https://www.google.com/?q=happy c++"
. Sembra che debba dividere manualmente "?" O c'è un modo migliore?
EscapeDataString
. Se l'URL che hai fornito è l'URL effettivo, quindi sì, vuoi semplicemente dividere ?
.
I commenti nella fonte affrontano chiaramente la differenza. Perché queste informazioni non vengano portate avanti tramite i commenti sulla documentazione XML è un mistero per me.
EscapeUriString:
Questo metodo sfuggirà a qualsiasi carattere che non sia un carattere riservato o senza prenotazione, inclusi i segni di percentuale. Si noti che anche EscapeUriString non sfuggirà a un segno '#'.
EscapeDataString:
Questo metodo sfuggirà a qualsiasi personaggio che non sia un personaggio senza prenotazione, inclusi i segni di percentuale.
Quindi la differenza sta nel modo in cui gestiscono i caratteri riservati . EscapeDataString
li sfugge; EscapeUriString
non.
Secondo la RFC , i caratteri riservati sono::/?#[]@!$&'()*+,;=
Per completezza, i caratteri senza prenotazione sono alfanumerici e -._~
Entrambi i metodi sfuggono ai caratteri che non sono né riservati né senza prenotazione.
Non sono d'accordo con l' idea generale che EscapeUriString
è malvagia. Penso che sia utile un metodo che sfugga solo ai personaggi illegali (come gli spazi) e ai caratteri non riservati . Ma ha una stranezza nel modo in cui gestisce il %
personaggio. I caratteri con codifica percentuale ( %
seguiti da 2 cifre esadecimali) sono legali in un URI. Penso che EscapeUriString
sarebbe molto più utile se rilevasse questo schema ed evitasse la codifica %
quando è immediatamente seguito da 2 cifre esadecimali.
Un semplice esempio
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()
, come spiegato nella risposta di @ Livven. Con altri approcci, il sistema semplicemente non ha abbastanza informazioni per produrre il risultato previsto per ogni possibile input.