Comment pouvez-vous UrlEncode sans utiliser System.Web?

310

J'essaie d'écrire une application client Windows qui appelle un site Web pour les données. Pour garder l'installation au minimum, j'essaie uniquement d'utiliser des DLL dans le profil client .NET Framework . Le problème est que j'ai besoin d'UrlEncode certains paramètres, existe-t-il un moyen facile de le faire sans importer System.Web.dll qui ne fait pas partie du profil client?

Martin Brown
la source
Pourriez-vous montrer comment effectuez-vous l'appel sur le site Web? Il y a peut-être quelque chose à faire là-bas.
Darin Dimitrov
Par curiosité, comment appeler un site Web pour des données sans utiliser System.Web?
Patrick McDonald
@Patrick, il utilise probablement WebRequestou WebClient. C'est la raison pour laquelle j'ai posé des questions sur ce code particulier, car il y a des choses à faire pour encoder correctement les données url.
Darin Dimitrov
1
J'utilise un objet System.Net.WebRequest. Ensuite, j'appelle GetRequestStream et j'écris mes paramètres Post dans le flux. J'ai également défini le ContentType sur "application / x-www-form-urlencoded".
Martin Brown
1
Bien sûr, cela s'appliquerait également si j'effectuais une demande GET et ajoutais les paramètres à l'URL.
Martin Brown

Réponses:

317

System.Uri.EscapeUriString() peut être problématique avec certains caractères, pour moi c'était un signe nombre / livre '#' dans la chaîne.

Si cela vous pose problème, essayez:

System.Uri.EscapeDataString() //Works excellent with individual values

Voici une réponse à une question SO qui explique la différence:

Quelle est la différence entre EscapeUriString et EscapeDataString?

et recommande d'utiliser Uri.EscapeDataString()dans tous les aspects.

ToddBFisher
la source
1
Faux: blogs.msdn.com/b/yangxind/archive/2006/11/09/… Vous aurez des problèmes avec les signes plus car ils ne seront pas non encodés.
Chris Weber
7
Ce billet de blog est un peu ancien et j'ai juste "Uri Escaped" une URL complète et tous les espaces sont devenus% 20, donc je pense qu'ils l'ont corrigé. J'utilise .Net 4.5.
Rodi
EscapeDataString ne prend pas non plus en charge les chaînes très longues si vous préparez des données pour une opération POST. stackoverflow.com/questions/6695208/…
Bron Davies
Uri.EscapeUriStringest en effet très problématique et ne doit pas être utilisé, car il essaie de faire quelque chose (échapper les URI complets) qui est en fait impossible à faire de manière cohérente Voir cette réponse pour une explication détaillée.
Livven
Également un caractère d'espace.
Waqas Shabbir
252

Dans .Net 4.5+, utilisez WebUtility

Juste pour le formatage, je soumets ceci comme réponse.

Impossible de trouver de bons exemples pour les comparer:

string testString = "http://test# space 123/text?var=val&another=two";
Console.WriteLine("UrlEncode:         " + System.Web.HttpUtility.UrlEncode(testString));
Console.WriteLine("EscapeUriString:   " + Uri.EscapeUriString(testString));
Console.WriteLine("EscapeDataString:  " + Uri.EscapeDataString(testString));
Console.WriteLine("EscapeDataReplace: " + Uri.EscapeDataString(testString).Replace("%20", "+"));

Console.WriteLine("HtmlEncode:        " + System.Web.HttpUtility.HtmlEncode(testString));
Console.WriteLine("UrlPathEncode:     " + System.Web.HttpUtility.UrlPathEncode(testString));

//.Net 4.0+
Console.WriteLine("WebUtility.HtmlEncode: " + WebUtility.HtmlEncode(testString));
//.Net 4.5+
Console.WriteLine("WebUtility.UrlEncode:  " + WebUtility.UrlEncode(testString));

Les sorties:

UrlEncode:             http%3a%2f%2ftest%23+space+123%2ftext%3fvar%3dval%26another%3dtwo
EscapeUriString:       http://test#%20space%20123/text?var=val&another=two
EscapeDataString:      http%3A%2F%2Ftest%23%20space%20123%2Ftext%3Fvar%3Dval%26another%3Dtwo
EscapeDataReplace:     http%3A%2F%2Ftest%23+space+123%2Ftext%3Fvar%3Dval%26another%3Dtwo

HtmlEncode:            http://test# space 123/text?var=val&another=two
UrlPathEncode:         http://test#%20space%20123/text?var=val&another=two

//.Net 4.0+
WebUtility.HtmlEncode: http://test# space 123/text?var=val&another=two
//.Net 4.5+
WebUtility.UrlEncode:  http%3A%2F%2Ftest%23+space+123%2Ftext%3Fvar%3Dval%26another%3Dtwo

Dans .Net 4.5+, utilisez WebUtility.UrlEncode

Cela semble se répliquer HttpUtility.UrlEncode(avant la v4.0) pour les caractères les plus courants:
Uri.EscapeDataString(testString).Replace("%20", "+").Replace("'", "%27").Replace("~", "%7E")
Remarque: EscapeUriStringconservera une chaîne uri valide, ce qui l'amènera à utiliser autant de caractères en clair que possible.

Voir cette réponse pour un tableau comparant les différents encodages:
https://stackoverflow.com/a/11236038/555798

Sauts de ligne Tous les éléments répertoriés ici (autres que HttpUtility.HtmlEncode) seront convertis "\n\r"en %0a%0dou%0A%0D

N'hésitez pas à le modifier et à ajouter de nouveaux caractères à ma chaîne de test, ou laissez-les dans les commentaires et je le modifierai.

Thymine
la source
Dans mon cas, j'ai dû utiliser EscapeDataStringplutôt que EscapeUriStringpendant que nous codions les retours chariot et les sauts de ligne et ceux-ci ont nécessité l'échappement le plus agressif effectué parEscapeDataString
David O'Meara
1
plus d'exemples, vous pouvez fournir vos propres cas de test si vous le souhaitez. Voici un exemple d'exécution et les autres méthodes d'encodage qui montrent les différences dotnetfiddle.net/12IFw1
Maslow
3
WebUtility.UrlEncode () et WebUtility.UrlDecode () sont 4.5+. Ils n'existent pas dans 4.0.
Derek Kalweit
Le msdn dit: "Plateforme Windows universelle: disponible depuis 4.5, .NET Framework: disponible depuis 4.0" ...
Thymine
54

Vous pouvez utiliser

Uri.EscapeUriString (voir http://msdn.microsoft.com/en-us/library/system.uri.escapeuristring.aspx )

Matthew Manela
la source
Y a-t-il une différence entre ceci et EscapeDataString?
Martin Brown
3
Vous souhaitez utiliser EscapeUriString. L'EscapeUriString essaiera d'encoder l'URL entière (incluez http: // part) tandis qu'EscapeUriString comprend quelles parties devraient être réellement encodées
Matthew Manela
1
Je vois, donc dans ce cas, je voudrais probablement EscapeDataString car je peux vouloir passer une URL comme paramètre get. J'ajoute à une URL dans ce cas.
Martin Brown
5
@MatthewManela Je suis sûr que votre commentaire du 1er octobre devrait lire The EscapeDataString va essayer de coder ...
Maslow
Ne pas utiliser Uri.EscapeUriString. Il ne "comprend" pas les parties qui doivent être encodées, c'est juste une tentative erronée de faire quelque chose (échapper les URI complets) qui est en fait impossible à faire de manière cohérente. Voir cette réponse pour une explication détaillée.
Livven
20

Les réponses ici sont très bonnes, mais encore insuffisantes pour moi.

J'ai écrit une petite boucle qui se compare Uri.EscapeUriStringà Uri.EscapeDataStringpour tous les caractères de 0 à 255.

REMARQUE: Les deux fonctions ont l'intelligence intégrée que les caractères supérieurs à 0x80 sont d'abord encodés en UTF-8 puis encodés en pourcentage.

Voici le résultat:

******* Different *******

'#' -> Uri "#" Data "%23"
'$' -> Uri "$" Data "%24"
'&' -> Uri "&" Data "%26"
'+' -> Uri "+" Data "%2B"
',' -> Uri "," Data "%2C"
'/' -> Uri "/" Data "%2F"
':' -> Uri ":" Data "%3A"
';' -> Uri ";" Data "%3B"
'=' -> Uri "=" Data "%3D"
'?' -> Uri "?" Data "%3F"
'@' -> Uri "@" Data "%40"


******* Not escaped *******

'!' -> Uri "!" Data "!"
''' -> Uri "'" Data "'"
'(' -> Uri "(" Data "("
')' -> Uri ")" Data ")"
'*' -> Uri "*" Data "*"
'-' -> Uri "-" Data "-"
'.' -> Uri "." Data "."
'_' -> Uri "_" Data "_"
'~' -> Uri "~" Data "~"

'0' -> Uri "0" Data "0"
.....
'9' -> Uri "9" Data "9"

'A' -> Uri "A" Data "A"
......
'Z' -> Uri "Z" Data "Z"

'a' -> Uri "a" Data "a"
.....
'z' -> Uri "z" Data "z"

******* UTF 8 *******

.....
'Ò' -> Uri "%C3%92" Data "%C3%92"
'Ó' -> Uri "%C3%93" Data "%C3%93"
'Ô' -> Uri "%C3%94" Data "%C3%94"
'Õ' -> Uri "%C3%95" Data "%C3%95"
'Ö' -> Uri "%C3%96" Data "%C3%96"
.....

EscapeUriStringdoit être utilisé pour coder les URL, tandis que EscapeDataStringdoit être utilisé pour coder par exemple le contenu d'un cookie, car les données du cookie ne doivent pas contenir les caractères réservés '='et ';'.

Elmue
la source
belle analyse et ventilation ici, très utile. si quelqu'un a ou connaît des critères de performance (en comparant les trois méthodes), ce serait également agréable à voir
Shaun Wilson
Il s'agit d'une bonne analyse et la conclusion est que vous ne devriez pas l'utiliser Uri.EscapeUriString, car il est impossible de s'échapper de manière cohérente pour échapper des URI complets. Voir cette réponse pour une explication détaillée.
Livven
16

Il existe une version utilisable du profil client, classe System.Net.WebUtility, présente dans le profil client System.dll. Voici le lien MSDN:

WebUtility

Sprague
la source
Je noterais que la page d'aide de cette classe indique spécifiquement "Fournit des méthodes de codage et de décodage des URL lors du traitement des demandes Web". il se pourrait donc qu'ils n'aient pas bien nommé les méthodes.
James White
Bon point, disons, pourquoi ne votez-vous pas pour un frère;) ce vote vers le bas me hante depuis 2 ans! JK ... mais honnêtement c'est probablement la raison pour laquelle j'ai posté le lien, dommage que je prenne un coup de réputation pour les erreurs dans les documents de Microsoft ...
Sprague
11
Il semble que UrlEncode et UrlDecode n'aient été ajoutés à WebUtility que dans la version 4.5 de .Net.
Martin Brown
8

Voici un exemple d'envoi d'une demande POST qui code correctement les paramètres à l'aide application/x-www-form-urlencodeddu type de contenu:

using (var client = new WebClient())
{
    var values = new NameValueCollection
    {
        { "param1", "value1" },
        { "param2", "value2" },
    };
    var result = client.UploadValues("http://foo.com", values);
}
Darin Dimitrov
la source
-3
System.Net.WebUtility.HtmlDecode
user3105093
la source
La classe WebUtility fournit des méthodes d'encodage et de décodage d'URL lors du traitement des demandes Web. Il fait la même chose que HttpUtility mais il est hors de l'espace de noms System.Web
Alexandru Aliu
3
C'est faux car il HtmlDecodes et ne UrlEncode comme la question posée. Même HtmlEncode serait faux car le codage HTML est différent du codage URL.
Martin Brown