Si je souhaite soumettre une requête http get en utilisant System.Net.HttpClient, il ne semble pas y avoir d'API pour ajouter des paramètres, est-ce correct?
Existe-t-il une API simple disponible pour créer la chaîne de requête qui n'implique pas la création d'une collection de valeurs de nom et un encodage d'URL, puis leur concaténation? J'espérais utiliser quelque chose comme l'api de RestSharp (c'est-à-dire AddParameter (..))
Réponses:
Oui.
Sûr:
vous donnera le résultat attendu:
Vous pourriez également trouver la
UriBuilder
classe utile:vous donnera le résultat attendu:
que vous pourriez plus que sans risque nourrir votre
HttpClient.GetAsync
méthode.la source
#
) pour vous en utilisant la propriété Fragment. J'ai vu tant de gens faire l'erreur de gérer manuellement les URL au lieu d'utiliser les outils intégrés.NameValueCollection.ToString()
ne crée normalement pas de chaînes de requête, et il n'y a pas de documentation indiquant que faire unToString
sur le résultat deParseQueryString
entraînera une nouvelle chaîne de requête, donc pourrait être interrompue à tout moment car il n'y a aucune garantie dans cette fonctionnalité.Pour ceux qui ne souhaitent pas l'inclure
System.Web
dans des projets qui ne l'utilisent pas déjà, vous pouvez utiliserFormUrlEncodedContent
fromSystem.Net.Http
et faire quelque chose comme ce qui suit:version keyvaluepair
version du dictionnaire
la source
dispose
? Je jette toujours à moins d'avoir une bonne raison de ne pas le faire, comme la réutilisationHttpClient
.TL; DR: n'utilisez pas la version acceptée car elle est complètement cassée par rapport à la gestion des caractères unicode, et n'utilisez jamais d'API interne
J'ai en fait trouvé un problème de double encodage étrange avec la solution acceptée:
Donc, si vous avez affaire à des caractères qui doivent être encodés, la solution acceptée conduit à un double encodage:
NameValueCollection
indexeur ( et cela utiliseUrlEncodeUnicode
, pas normalement prévuUrlEncode
(!) )uriBuilder.Uri
il crée un nouveauUri
constructeur utilisant qui encode une fois de plus (encodage url normal)uriBuilder.ToString()
(même si cela renvoie correctUri
quel IMO est au moins incohérent, peut-être un bogue, mais c'est une autre question), puis en utilisant laHttpClient
méthode acceptant la chaîne - le client crée toujours àUri
partir de votre chaîne passée comme ceci:new Uri(uri, UriKind.RelativeOrAbsolute)
Petit, mais repro complet:
Production:
Comme vous pouvez le voir, peu importe si vous faites
uribuilder.ToString()
+httpClient.GetStringAsync(string)
ouuriBuilder.Uri
+httpClient.GetStringAsync(Uri)
vous finissez par envoyer un paramètre codé en doubleUn exemple fixe pourrait être:
Mais cela utilise un
Uri
constructeur obsolètePS sur mon dernier .NET sur Windows Server, le
Uri
constructeur avec un commentaire booléen dit "obsolète, dontEscape est toujours faux", mais fonctionne en fait comme prévu (saute l'échappement)Donc ça ressemble à un autre bug ...
Et même cela est tout simplement faux - il envoie UrlEncodedUnicode au serveur, pas seulement UrlEncoded ce que le serveur attend
Mise à jour: une dernière chose est que NameValueCollection fait réellement UrlEncodeUnicode, qui n'est plus censé être utilisé et est incompatible avec url.encode / décodage régulier (voir NameValueCollection to URL Query? ).
Donc, l'essentiel est: n'utilisez jamais ce hack avec
NameValueCollection query = HttpUtility.ParseQueryString(builder.Query);
car cela perturberait vos paramètres de requête Unicode. Créez simplement la requête manuellement et assignez-la àUriBuilder.Query
laquelle effectuera le codage nécessaire, puis obtenez Uri à l'aide deUriBuilder.Uri
.Premier exemple de vous blesser en utilisant du code qui n'est pas censé être utilisé comme ça
la source
var namedValues = HttpUtility.ParseQueryString(builder.Query)
, mais au lieu d'utiliser le NameValueCollection retourné, convertissez-le immédiatement en un dictionnaire comme ceci:var dic = values.ToDictionary(x => x, x => values[x]);
Ajoutez de nouvelles valeurs au dictionnaire, puis passez-le au constructeur deFormUrlEncodedContent
et appelez-ReadAsStringAsync().Result
le. Cela vous donne une chaîne de requête correctement codée, que vous pouvez réattribuer à UriBuilder.<add key="aspnet:DontUsePercentUUrlEncoding" value="true" />
. Je ne dépendrais pas de ce comportement, il est donc préférable d'utiliser la classe FormUrlEncodedContent, comme le montre une réponse précédente: stackoverflow.com/a/26744471/88409Dans un projet ASP.NET Core, vous pouvez utiliser la classe QueryHelpers.
la source
Vous voudrez peut-être consulter Flurl [divulgation: je suis l'auteur], un constructeur d'URL fluide avec une bibliothèque compagnon en option qui l'étend en un client REST à part entière.
Consultez les documents pour plus de détails. Le package complet est disponible sur NuGet:
PM> Install-Package Flurl.Http
ou simplement le générateur d'URL autonome:
PM> Install-Package Flurl
la source
Uri
ou commencer avec votre propre classe au lieu destring
?Url
classe. Ce qui précède est équivalent ànew Url("https://api.com").AppendPathSegment...
Personnellement, je préfère les extensions de chaîne en raison du moins de frappes au clavier et standardisées sur elles dans la documentation, mais vous pouvez le faire de toute façon.Dans le même esprit que l'article de Rostov, si vous ne souhaitez pas inclure de référence à
System.Web
dans votre projet, vous pouvez utiliserFormDataCollection
fromSystem.Net.Http.Formatting
et faire quelque chose comme ce qui suit:En utilisant
System.Net.Http.Formatting.FormDataCollection
la source
Darin a proposé une solution intéressante et intelligente, et voici quelque chose qui pourrait être une autre option:
et donc lors de son utilisation, vous pouvez faire ceci:
la source
kvp.Key
etkvp.Value
séparément dans la boucle for, pas dans la chaîne de requête complète (donc pas encoder les caractères&
, et=
).server.UrlEncode
peut être remplacé parWebUtility.UrlEncode
Ou simplement en utilisant mon extension Uri
Code
Usage
Résultat
la source
La bibliothèque de modèles d'URI RFC 6570 que je développe est capable d'effectuer cette opération. Tout le codage est géré pour vous conformément à cette RFC. Au moment d'écrire ces lignes, une version bêta est disponible et la seule raison pour laquelle elle n'est pas considérée comme une version 1.0 stable est que la documentation ne répond pas entièrement à mes attentes (voir les problèmes # 17 , # 18 , # 32 , # 43 ).
Vous pouvez soit créer une chaîne de requête seule:
Ou vous pouvez créer un URI complet:
la source
Comme je dois réutiliser cette fois-ci, j'ai créé cette classe qui aide simplement à résumer la composition de la chaîne de requête.
L'utilisation sera simplifiée à quelque chose comme ceci:
qui renverra l'URI: http://example.com/?foo=bar%3c%3e%26-baz&bar=second
la source
Pour éviter le problème de double codage décrit dans la réponse de taras.roshko et pour garder la possibilité de travailler facilement avec les paramètres de requête, vous pouvez utiliser à la
uriBuilder.Uri.ParseQueryString()
place deHttpUtility.ParseQueryString()
.la source
Bonne partie de la réponse acceptée, modifiée pour utiliser UriBuilder.Uri.ParseQueryString () au lieu de HttpUtility.ParseQueryString ():
la source
ParseQueryString()
méthode d'extension n'est pas incluseSystem
.Merci à "Darin Dimitrov", ce sont les méthodes d'extension.
la source
Je n'ai pas pu trouver de meilleure solution que de créer une méthode d'extension pour convertir un dictionnaire en QueryStringFormat. La solution proposée par Waleed AK est également bonne.
Suivez ma solution:
Créez la méthode d'extension:
Et eux:
la source