Risposte:
HttpServerUtility.UrlEncode
userà HttpUtility.UrlEncode
internamente. Non c'è alcuna differenza specifica. Il motivo dell'esistenza di Server.UrlEncode
è la compatibilità con ASP classico.
Avevo avuto grossi mal di testa con questi metodi prima, ti consiglio di evitare qualsiasi variante UrlEncode
e invece di usareUri.EscapeDataString
- almeno quello ha un comportamento comprensibile.
Vediamo...
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
Ma il mio preferito personale deve essere HttpUtility.UrlPathEncode - questa cosa è davvero incomprensibile. Codifica:
Ha anche la documentazione specifica per MSDN "Codifica la parte del percorso di una stringa URL per una trasmissione HTTP affidabile dal server Web a un client." - senza realmente spiegare cosa fa. È meno probabile che ti spari al piede con un Uzi ...
In breve, attenersi a Uri.EscapeDataString .
?
e chi può dire quali devono essere codificati e quali fungono da separatori? Per quanto riguarda lo spazio: in entrambi i casi lo spazio è nell'hash, quindi la presenza o l'assenza di un frammento di query non dovrebbe avere importanza. E infine, è ingiustificabile corrompere un Uri come nel secondo esempio contenente un%. Il UrlPathEncode
metodo è semplice e non dovrebbe mai essere usato.
Avanti veloce da quasi 9 anni da quando è stato chiesto per la prima volta, e nel mondo di .NET Core e .NET Standard, sembra che le opzioni più comuni che abbiamo per la codifica URL siano WebUtility.UrlEncode (under System.Net
) e Uri.EscapeDataString . A giudicare dalla risposta più popolare qui e altrove, Uri.EscapeDataString sembra essere preferibile. Ma è? Ho fatto alcune analisi per capire le differenze ed ecco cosa mi è venuto in mente:
WebUtility.UrlEncode
codifica lo spazio come +
; Uri.EscapeDataString
lo codifica come %20
.Uri.EscapeDataString
cento-codifica !
, (
, )
, e *
; WebUtility.UrlEncode
non.WebUtility.UrlEncode
codifica percentuale ~
; Uri.EscapeDataString
non.Uri.EscapeDataString
genera UriFormatException
stringhe su più lunghe di 65.520 caratteri; WebUtility.UrlEncode
non. ( Un problema più comune di quanto si possa pensare, in particolare quando si tratta di dati di moduli con codifica URL .)Uri.EscapeDataString
getta una UriFormatException
sui caratteri surrogati alti ; WebUtility.UrlEncode
non. (Questa è una cosa UTF-16, probabilmente molto meno comune.)Ai fini della codifica URL, i caratteri rientrano in una delle 3 categorie: senza prenotazione (legale in un URL); riservato (legale ma ha un significato speciale, quindi potresti voler codificarlo); e tutto il resto (deve essere sempre codificato).
Secondo la RFC , i caratteri riservati sono::/?#[]@!$&'()*+,;=
E i personaggi senza prenotazione sono alfanumerici e -._~
Uri.EscapeDataString definisce chiaramente la sua missione:% -codifica tutti i personaggi riservati e illegali. WebUtility.UrlEncode è più ambiguo sia nella definizione che nell'implementazione. Stranamente, codifica alcuni caratteri riservati ma non altri (perché parentesi e non parentesi ??), e ancora più strano codifica quel ~
personaggio innocentemente senza riserve .
Pertanto, concordo con il consiglio popolare: utilizzare Uri.EscapeDataString quando possibile e capire che ai caratteri riservati piacciono /
e ?
verranno codificati. Se hai bisogno di gestire stringhe potenzialmente grandi, in particolare con il contenuto del modulo con codifica URL, dovrai ricorrere a WebUtility.UrlEncode e accettare le sue stranezze, o altrimenti risolvere il problema.
EDIT: Ho tentato di rettificare TUTTE le stranezze di cui sopra in Flurl attraverso i Url.Encode
, Url.EncodeIllegalCharacters
e Url.Decode
metodi statici. Questi sono nel pacchetto principale (che è minuscolo e non include tutto il materiale HTTP), o sentiti libero di strapparli dal sorgente. Sono lieto di ricevere qualsiasi commento / feedback in merito.
Ecco il codice che ho usato per scoprire quali caratteri sono codificati in modo diverso:
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}");
Tieni presente che probabilmente non dovresti utilizzare uno di questi metodi. La libreria di scripting Anti-Cross Site di Microsoft include sostituzioni per HttpUtility.UrlEncode
e HttpUtility.HtmlEncode
che sono entrambe più conformi agli standard e più sicure. Come bonus, ottieni anche un JavaScriptEncode
metodo.