Réponses:
Utilisez EscapeDataString
toujours (pour plus d'informations sur les raisons, voir la réponse de Livven ci-dessous)
Edit : suppression du lien mort sur la différence entre les deux sur le codage
URLEncode
aussi).
Je n'ai pas trouvé les réponses existantes satisfaisantes, j'ai donc décidé de creuser un peu plus pour régler ce problème. Étonnamment, la réponse est très simple:
Il n'y a (presque *) aucune raison valable de l'utiliser Uri.EscapeUriString
. Si vous devez encoder en pourcentage une chaîne, utilisez toujours Uri.EscapeDataString
.
* Voir le dernier paragraphe pour un cas d'utilisation valide.
Pourquoi est-ce? Selon la documentation :
Utilisez la méthode EscapeUriString pour préparer une chaîne d'URI sans échappement en tant que paramètre du constructeur Uri.
Cela n'a pas vraiment de sens. Selon RFC 2396 :
Un URI est toujours sous une forme «échappée», car échapper ou déséchapper un URI terminé peut changer sa sémantique.
Alors que la RFC citée est devenue obsolète par la RFC 3986 , le point est toujours d'actualité. Vérifions-le en regardant quelques exemples concrets:
Vous avez un URI simple, comme ceci:
http://example.org/
Uri.EscapeUriString
ne le changera pas.
Vous décidez de modifier manuellement la chaîne de requête sans tenir compte de l'échappement:
http://example.org/?key=two words
Uri.EscapeUriString
échappera (correctement) à l'espace pour vous:
http://example.org/?key=two%20words
Vous décidez de modifier encore plus manuellement la chaîne de requête:
http://example.org/?parameter=father&son
Cependant, cette chaîne n'est pas modifiée par Uri.EscapeUriString
, car elle suppose que l'esperluette signifie le début d'une autre paire clé-valeur. Cela peut ou non être ce que vous vouliez.
Vous décidez que vous voulez en fait que le key
paramètre soit father&son
, donc vous corrigez l'URL précédente manuellement en échappant l'esperluette:
http://example.org/?parameter=father%26son
Cependant, Uri.EscapeUriString
le caractère de pourcentage échappera également, ce qui entraînera un double encodage:
http://example.org/?parameter=father%2526son
Comme vous pouvez le voir, l'utilisation Uri.EscapeUriString
pour son usage prévu rend impossible l'utilisation&
comme partie d'une clé ou d'une valeur dans une chaîne de requête plutôt que comme séparateur entre plusieurs paires clé-valeur.
En effet, pour tenter de le rendre approprié pour échapper des URI complets, il ignore les caractères réservés et n'échappe que les caractères qui ne sont ni réservés ni non réservés, ce qui, BTW, est contraire à la documentation . De cette façon, vous ne vous retrouvez pas avec quelque chose comme http%3A%2F%2Fexample.org%2F
, mais vous vous retrouvez avec les problèmes illustrés ci-dessus.
En fin de compte, si votre URI est valide, il n'a pas besoin d'être échappé pour être passé en paramètre au constructeur d'Uri, et s'il n'est pas valide, appelez Uri.EscapeUriString
n'est pas non plus une solution magique. En fait, cela fonctionnera dans de nombreux cas sinon dans la plupart des cas, mais ce n'est en aucun cas fiable.
Vous devez toujours créer vos URL et vos chaînes de requête en rassemblant les paires clé-valeur et le codage en pourcentage, puis en les concaténant avec les séparateurs nécessaires. Vous pouvez utiliser Uri.EscapeDataString
à cette fin, mais pas Uri.EscapeUriString
, car il n'échappe pas aux caractères réservés, comme mentionné ci-dessus.
Ce n'est que si vous ne pouvez pas faire cela, par exemple lorsque vous traitez avec des URI fournis par l'utilisateur, qu'il est judicieux de l'utiliser Uri.EscapeUriString
en dernier recours. Mais les mises en garde mentionnées précédemment s'appliquent - si l'URI fourni par l'utilisateur est ambigu, les résultats peuvent ne pas être souhaitables.
encodeURI
/ Uri.EscapeUriString
n'est pas nécessaire aussi souvent que encodeURIComponent
/ Uri.EscapeDataString
(depuis quand faites-vous la sourde oreille avec des URL aveugles qui doivent être utilisées dans un contexte uri), mais cela ne veut pas dire qu'elle n'a pas sa place.
Les caractères plus (+) peuvent en dire long sur la différence entre ces méthodes. Dans un URI simple, le caractère plus signifie «espace». Envisagez d'interroger Google sur "chat heureux":
C'est un URI valide (essayez-le), et EscapeUriString
ne le modifiera pas.
Pensez maintenant à interroger Google pour "happy c ++":
C'est un URI valide (essayez-le), mais cela produit une recherche pour "happy c", car les deux plus sont interprétés comme des espaces. Pour le réparer, nous pouvons passer "happy c ++" à EscapeDataString
et voila * :
*) La chaîne de données encodée est en fait "happy% 20c% 2B% 2B"; % 20 est hexadécimal pour le caractère espace et% 2B est hexadécimal pour le caractère plus.
Si vous utilisez UriBuilder
comme vous le souhaitez, il vous suffira EscapeDataString
d'échapper correctement à certains des composants de l'ensemble de votre URI. La réponse de @ Livven à cette question prouve en outre qu'il n'y a vraiment aucune raison d'utiliser EscapeUriString
.
"https://www.google.com/?q=happy c++"
. Il semble que j'ai besoin de fractionner manuellement sur "?", Ou y a-t-il un meilleur moyen?
EscapeDataString
. Si l'URL que vous avez fournie est l'URL réelle, alors oui, vous voulez simplement diviser ?
.
Commentaires dans la source abordent clairement la différence. Pourquoi ces informations ne sont pas transmises via les commentaires de documentation XML est un mystère pour moi.
EscapeUriString:
Cette méthode échappera à tout caractère qui n'est pas un caractère réservé ou non réservé, y compris les signes de pourcentage. Notez que EscapeUriString n'échappera pas non plus au signe «#».
EscapeDataString:
Cette méthode échappera à tout caractère qui n'est pas un caractère non réservé, y compris les signes de pourcentage.
La différence réside donc dans la manière dont ils gèrent les caractères réservés . EscapeDataString
leur échappe;EscapeUriString
ne fait pas.
Selon la RFC , les caractères réservés sont::/?#[]@!$&'()*+,;=
Par souci d'exhaustivité, les caractères non réservés sont alphanumériques et -._~
Les deux méthodes échappent aux caractères qui ne sont ni réservés ni non réservés.
Je suis en désaccord avec le général notion qui EscapeUriString
est mal. Je pense qu'une méthode qui échappe uniquement aux caractères illégaux (tels que les espaces) et non aux caractères réservés est utile. Mais il a une bizarrerie dans la façon dont il gère le %
personnage. Les caractères codés en pourcentage ( %
suivis de 2 chiffres hexadécimaux) sont autorisés dans un URI. Je pense que ce EscapeUriString
serait beaucoup plus utile s'il détectait ce modèle et évitait le codage %
lorsqu'il était immédiatement procédé par 2 chiffres hexadécimaux.
Un exemple simple
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()
, comme expliqué dans la réponse de @ Livven. Avec d'autres approches, le système n'a tout simplement pas assez d'informations pour produire le résultat attendu pour chaque entrée possible.