Qual è la differenza tra EscapeUriString e EscapeDataString?


196

Se dovessi occuparmi solo della codifica degli URL, dovrei usare EscapeUriString ?


10
Sfuggire sempre a ogni singolo valore usando 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.
Timo,

Risposte:


112

Usa EscapeDataStringsempre (per maggiori informazioni sul perché, vedi la risposta di Livven di seguito)

Modifica : rimosso il link morto su come i due differiscono nella codifica


3
Non sono sicuro che il link in realtà fornisca ulteriori informazioni in quanto riguarda l'escaping piuttosto che l'esacaping.
Steven,

1
È sostanzialmente la stessa differenza. Se leggi effettivamente l'articolo, c'è una tabella intorno al centro che effettivamente sfugge (non unescapes) per mostrare le differenze (confrontando URLEncodeanche con ).
Jcl

2
Non mi è ancora chiaro - cosa succede se non sto eseguendo l'escape di un intero URI ma solo di una parte di esso (ovvero i dati per un parametro della stringa di query)? Sto sfuggendo ai dati per l'URI o EscapeDataString implica qualcosa di completamente diverso?
BrainSlugs83

4
... alcuni test sembrano voler EscapeDataString per un parametro URI. Ho provato con la stringa "I heart C ++" ed EscapeUriString non ha codificato i caratteri "+", li ha lasciati così come sono, EscapeDataString li ha convertiti correttamente in "% 2B".
BrainSlugs83

7
Questa è una cattiva risposta Non dovresti mai usare EscapeUriString, non ha alcun senso. Vedi la risposta di Livven di seguito (e votala).
Brandon Paddock,

245

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:

  1. Hai un URI semplice, come questo:

    http://example.org/

    Uri.EscapeUriString non lo cambierà.

  2. 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
  3. 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.

  4. Decidi di voler effettivamente essere il keyparametro father&son, quindi correggi manualmente l'URL precedente sfuggendo alla e commerciale:

    http://example.org/?parameter=father%26son

    Tuttavia, Uri.EscapeUriStringsfuggirà anche al carattere percentuale, portando a una doppia codifica:

    http://example.org/?parameter=father%2526son

Come puoi vedere, l'uso Uri.EscapeUriStringper 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.EscapeDataStringper 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.EscapeUriStringcome ultima risorsa. Ma si applicano le avvertenze menzionate in precedenza: se l'URI fornito dall'utente è ambiguo, i risultati potrebbero non essere desiderabili.


4
Wow, grazie per aver chiarito finalmente questo problema. Le due precedenti risposte non sono state molto utili.
EverPresent,

3
Completamente giusto. EscapeUriString (come il comportamento predefinito di EscapeUrl in Win32) è stato creato da qualcuno che non capiva gli URI o fuggiva. È un tentativo fuorviato di creare qualcosa che prende un URI non valido e talvolta lo trasforma nella versione prevista. Ma non ha le informazioni necessarie per farlo in modo affidabile. Inoltre viene spesso utilizzato al posto di EscapeDataString, che è anche molto problematico. Vorrei che EscapeUriString non esistesse. Ogni suo utilizzo è sbagliato.
Brandon Paddock,

4
ben spiegato +1 è molto meglio del link accettato solo risposta
Ehsan Sajjad

1
Questa risposta richiede più attenzione. È il modo corretto di farlo. Le altre risposte presentano scenari in cui non producono i risultati previsti.
Timo,

1
... Certo encodeURI/ Uri.EscapeUriStringnon è necessario con la stessa frequenza di ( encodeURIComponent/ Uri.EscapeDataStringda quando stai cantando con url ciechi che devono essere usati in un contesto uri), ma ciò non significa che non abbia il suo posto.
Crescent Fresh,

56

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":

https://www.google.com/?q=happy+cat

È un URI valido (provalo) e EscapeUriStringnon lo modificherà.

Ora considera di interrogare Google per "happy c ++":

https://www.google.com/?q=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 EscapeDataStringe voilà * :

https://www.google.com/?q=happy+c%2B%2B

*) 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 UriBuildercome dovresti, dovrai solo EscapeDataStringsfuggire 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.


Grazie. Che dire di quando hai una stringa URI assoluta che devi codificare, per esempio "https://www.google.com/?q=happy c++". Sembra che debba dividere manualmente "?" O c'è un modo migliore?
mercoledì

Se stai passando l'intero URL come parametro a un altro URL, utilizza EscapeDataString. Se l'URL che hai fornito è l'URL effettivo, quindi sì, vuoi semplicemente dividere ?.
Seth,

7

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 . EscapeDataStringli sfugge; EscapeUriStringnon.

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 EscapeUriStringsarebbe molto più utile se rilevasse questo schema ed evitasse la codifica %quando è immediatamente seguito da 2 cifre esadecimali.


1

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
*/
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.