Qual è la differenza tra EscapeUriString e EscapeDataString?

Se gestisco solo la codifica dell’URL , dovrei usare EscapeUriString ?

Si utilizza EscapeUriString se ciò che si sta sfuggendo è un URI e EscapeDataString qualsiasi altro luogo.

Ci sono differenze su come quei due codificano le corde.

Maggiori informazioni qui: http://blogs.msdn.com/b/yangxind/archive/2006/11/09/don-t-use-net-system-uri-unescapedatastring-in-url-decoding.aspx

Non ho trovato soddisfacenti le risposte esistenti, quindi ho deciso di scavare un po ‘più a fondo per risolvere questo problema. Sorprendentemente, la risposta è molto semplice:

Non c’è motivo valido per utilizzare mai Uri.EscapeUriString . Se è necessario codificare in percentuale una stringa, utilizzare sempre Uri.EscapeDataString .

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 molto senso. Secondo RFC 2396 :

Un URI è sempre in un formato “escape”, dal momento che l’escape o il non escape di un URI completato potrebbe cambiare la sua semantica.

Mentre la RFC citata è stata obsoleta da RFC 3986 , il punto rimane valido. Verifichiamo esaminando alcuni esempi concreti:

  1. Hai un semplice URI, come questo:

     http://example.org/ 

    Uri.EscapeUriString non lo cambierà.

  2. Decidi di modificare manualmente la stringa di query senza riguardo per l’escape:

     http://example.org/?key=two words 

    Uri.EscapeUriString (correttamente) sfugge allo spazio per te:

     http://example.org/?key=two%20words 
  3. Decidi di modificare manualmente la stringa di query ulteriormente:

     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 potrebbe o non potrebbe essere ciò che intendevi.

  4. Decidi che in effetti vuoi che il parametro key sia father&son , quindi aggiusti manualmente l’URL precedente eseguendo l’escape della e commerciale:

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

    Tuttavia, Uri.EscapeUriString sfugge anche al carattere percentuale, determinando una doppia codifica:

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

Come puoi vedere, l’uso di Uri.EscapeUriString per lo scopo previsto rende imansible l’utilizzo di & come parte di una chiave o valore in una stringa di query anziché come separatore tra più coppie chiave-valore.

Questo perché, in un tentativo fuorviante di renderlo adatto per l’escape di URI completi, ignora i caratteri riservati e sfugge solo caratteri che non sono né riservati né riservati, il che, in realtà, è contrario alla documentazione . In questo modo non si finisce con qualcosa come http%3A%2F%2Fexample.org%2F , ma si finisce con i problemi illustrati sopra.


Alla fine, se l’URI è valido, non ha bisogno di essere scappato per essere passato come parametro al costruttore di Uri, e se non è valido, allora 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 build i tuoi URL e interrogare le stringhe raccogliendo le coppie chiave-valore e la codifica percentuale e quindi concatenandole con i separatori necessari. È ansible utilizzare Uri.EscapeDataString per questo scopo, ma non Uri.EscapeUriString , poiché non sfugge ai caratteri riservati, come menzionato sopra.

I più (+) caratteri possono rivelare molto sulla differenza tra questi metodi. In un semplice URI, il carattere più significa “spazio”. Considera di interrogare Google per “happy cat”:

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

Questo è un URI valido (provalo) e EscapeUriString non lo modificherà.

Ora considera l’interrogazione di Google per “happy c ++”:

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

Questo è un URI valido (provalo), ma produce una ricerca per “felice c”, perché i due vantaggi sono interpretati come spazi. Per risolvere il problema, possiamo passare “happy c ++” a EscapeDataString e voilà * :

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

*) La stringa di dati codificati è in realtà “felice% 20c% 2B% 2B”; % 20 è esadecimale per il carattere spazio e% 2B è esadecimale per il carattere più.

Se stai usando UriBuilder come dovresti, allora avrai solo bisogno di EscapeDataString per uscire correttamente da alcuni dei componenti dell’intero URI. @ La risposta di Livven a questa domanda dimostra che non c’è davvero alcun motivo per usare EscapeUriString .

I commenti nell’indirizzo sorgente indicano chiaramente la differenza. Perché questa informazione non viene anticipata tramite i commenti della documentazione XML è un mistero per me.

EscapeUriString:

Questo metodo sfuggirà a qualsiasi carattere che non sia un carattere riservato o non prenotato, compresi i segni di percentuale. Nota che EscapeUriString non sfuggirà nemmeno al segno “#”.

EscapeDataString:

Questo metodo sfugge a qualsiasi personaggio che non sia un personaggio non prenotato, compresi i segni di percentuale.

Quindi la differenza sta nel modo in cui gestiscono i personaggi riservati . EscapeDataString li sfugge; EscapeUriString no.

Secondo la RFC , i caratteri riservati sono:: :/?#[]@!$&'()*+,;=

Per completezza, i caratteri non riservati sono alfanumerici e -._~

Entrambi i metodi sfuggono ai caratteri che non sono né riservati né riservati.

Non sono d’accordo con l’ idea generale che EscapeUriString sia malvagio. Penso che un metodo che sfugge solo caratteri illegali (come spazi) e caratteri non riservati è utile. Ma ha una stranezza nel modo in cui gestisce il carattere % . 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 pattern ed evitasse la codifica % quando è immediatamente preceduta 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 */