Une tâche courante lors de l'appel de ressources Web à partir d'un code consiste à créer une chaîne de requête pour inclure tous les paramètres nécessaires. Bien que ce ne soit absolument pas une science de fusée, il y a quelques détails astucieux dont vous devez vous occuper, comme l'ajout d'un &
sinon le premier paramètre, l'encodage des paramètres, etc.
Le code pour le faire est très simple, mais un peu fastidieux:
StringBuilder SB = new StringBuilder();
if (NeedsToAddParameter A)
{
SB.Append("A="); SB.Append(HttpUtility.UrlEncode("TheValueOfA"));
}
if (NeedsToAddParameter B)
{
if (SB.Length>0) SB.Append("&");
SB.Append("B="); SB.Append(HttpUtility.UrlEncode("TheValueOfB")); }
}
C'est une tâche si courante que l'on s'attendrait à ce qu'il existe une classe d'utilité qui la rende plus élégante et lisible. En scannant MSDN, je n'ai pas réussi à en trouver un, ce qui m'amène à la question suivante:
Quelle est la façon la plus propre et la plus élégante de faire ce qui précède?
c#
.net
url
query-string
Boaz
la source
la source
Réponses:
Si vous regardez sous le capot, la propriété QueryString est un NameValueCollection. Quand j'ai fait des choses similaires, j'ai généralement été intéressé par la sérialisation ET la désérialisation, donc ma suggestion est de construire un NameValueCollection et de passer ensuite à:
J'imagine qu'il y a une manière super élégante de faire ça dans LINQ aussi ...
la source
application/x-www-form-urlencoded
et est en fait défini par HTML, dans le but de soumettre des données de formulaire dans le cadre d'uneGET
demande. HTML 5 n'interdit pas plusieurs valeurs par clé dans ce format, et en fait il nécessite que le navigateur produise plusieurs valeurs par clé dans le cas où la page contient (incorrectement) plusieurs champs avec le mêmename
attribut. Voir goo.gl/uk1AgVous pouvez créer une nouvelle instance accessible en écriture de
HttpValueCollection
en appelantSystem.Web.HttpUtility.ParseQueryString(string.Empty)
, puis l'utiliser comme n'importe quel autreNameValueCollection
. Une fois que vous avez ajouté les valeurs souhaitées, vous pouvez appelerToString
la collection pour obtenir une chaîne de requête, comme suit:Le
HttpValueCollection
est interne et vous ne pouvez donc pas construire directement une instance. Cependant, une fois que vous avez obtenu une instance, vous pouvez l'utiliser comme une autreNameValueCollection
. Étant donné que l'objet réel avec lequel vous travaillez est unHttpValueCollection
, l'appel à la méthode ToString appellera la méthode remplacéeHttpValueCollection
, qui formate la collection en tant que chaîne de requête codée URL.Après avoir recherché SO et le Web pour une réponse à un problème similaire, c'est la solution la plus simple que j'ai pu trouver.
.NET Core
Si vous travaillez dans .NET Core, vous pouvez utiliser la
Microsoft.AspNetCore.WebUtilities.QueryHelpers
classe, ce qui simplifie considérablement cela.https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.webutilities.queryhelpers
Exemple de code:
la source
public static string ToURLQueryString(this IDictionary dict) { ... }
Add
méthode. C'est-à-dire que l'queryString.Add("type", "1"); queryString.Add("type", "2");
utilisation de laAdd
méthode est probablement une meilleure façon de le faire tout le temps en fait.Avec l'inspiration du commentaire de Roy Tinker, j'ai fini par utiliser une méthode d'extension simple sur la classe Uri qui garde mon code concis et propre:
Usage:
Modifier - Variante conforme aux normes
Comme plusieurs personnes l'ont souligné,
httpValueCollection.ToString()
code les caractères Unicode d'une manière non conforme aux normes . Il s'agit d'une variante de la même méthode d'extension qui gère ces caractères en appelantHttpUtility.UrlEncode
méthode au lieu de laHttpUtility.UrlEncodeUnicode
méthode obsolète .la source
J'ai répondu à une question similaire il y a quelque temps. Fondamentalement, la meilleure façon serait d'utiliser la classe
HttpValueCollection
, qui est ASP.NETRequest.QueryString
est réellement la propriété , malheureusement elle est interne dans le framework .NET. Vous pouvez utiliser Reflector pour l'attraper (et le placer dans votre classe Utils). De cette façon, vous pouvez manipuler la chaîne de requête comme une NameValueCollection, mais avec tous les problèmes de codage / décodage d'URL pris en charge pour vous.HttpValueCollection
étendNameValueCollection
, et a un constructeur qui prend une chaîne de requête codée (esperluette et points d'interrogation inclus), et il remplace unToString()
méthode pour reconstruire ultérieurement la chaîne de requête à partir de la collection sous-jacente.Exemple:
la source
httpValueCollection.ToString()
appelle en fait,httpValueCollection.ToString(true)
iltrue
n'est donc pas nécessaire d' ajouter l' explicité.Voici un moyen fluide / lambda-ish comme méthode d'extension (combinant les concepts dans les articles précédents) qui prend en charge plusieurs valeurs pour la même clé. Ma préférence personnelle est les extensions sur les wrappers pour que les autres membres de l'équipe puissent les découvrir pour des choses comme ça. Notez qu'il ya une controverse autour de méthodes de codage, beaucoup de messages à ce sujet sur le débordement de pile (un tel poste ) et les blogueurs MSDN (comme celui - ci ).
edit: avec un support nul, mais vous devrez probablement l'adapter à votre situation particulière
la source
Flurl [divulgation: je suis l'auteur] prend en charge la création de chaînes de requête via des objets anonymes (entre autres):
La bibliothèque complémentaire Flurl.Http en option vous permet d'effectuer des appels HTTP directement à partir de la même chaîne d'appels fluide, en l'étendant dans un client REST complet:
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
Voici mon entrée tardive. Je n'aimais aucun des autres pour diverses raisons, alors j'ai écrit le mien.
Cette version comprend:
Utilisation de StringBuilder uniquement. Aucun appel ToArray () ou autres méthodes d'extension. Cela ne semble pas aussi joli que certaines des autres réponses, mais je considère que c'est une fonction de base, donc l'efficacité est plus importante que d'avoir un code "fluide", "à une ligne" qui cache les inefficacités.
Gère plusieurs valeurs par clé. (Je n'en avais pas besoin moi-même mais juste pour faire taire Mauricio;)
Exemple d'utilisation
Production
la source
Que diriez-vous de créer des méthodes d'extension qui vous permettent d'ajouter les paramètres dans un style fluide comme celui-ci?
Voici la surcharge qui utilise un
string
:Et voici la surcharge qui utilise un
StringBuilder
:la source
NameValueCollection
,HttpValueCollection
ou uneUri
première. Merci!J'avais besoin de résoudre le même problème pour une bibliothèque de classes portable (PCL) sur laquelle je travaille. Dans ce cas, je n'ai pas accès à System.Web donc je ne peux pas utiliser ParseQueryString.
Au lieu de cela, j'ai utilisé
System.Net.Http.FormUrlEncodedContent
comme ça:la source
la source
.ToArray()
s.Ajoutez cette classe à votre projet
Et utilisez-le comme ceci:
la source
Mon offre:
Usage:
la source
Non testé, mais je pense que quelque chose dans ce sens fonctionnerait très bien
la source
Une version basée sur une méthode d'extension rapide:
Vous pouvez utiliser une clause where pour sélectionner les paramètres à ajouter à la chaîne.
la source
En supposant que vous souhaitiez réduire les dépendances à d'autres assemblys et garder les choses simples, vous pouvez faire:
Cela fonctionne bien aussi avec les boucles. La suppression définitive de l'esperluette doit sortir de la boucle.
Notez que l'opérateur de concaténation est utilisé pour améliorer la lisibilité. Le coût de son utilisation par rapport au coût d'utilisation d'un StringBuilder est minime (je pense que Jeff Atwood a publié quelque chose sur ce sujet).
la source
Combiné les meilleures réponses pour créer une version d'objet anonyme :
Cela génère ceci:
Voici le code:
la source
Identique à la solution acceptée, mais transfred en syntaxe LINQ "dot" ...
la source
J'ai une méthode d'extension pour Uri qui:
uri.WithQuery(new { name = "value" })
string/string
paires (par exemple Dictionary`2 ).string/object
paires (par exemple RouteValueDictionary ).La version documentée peut être trouvée ici .
L'extension:
L'analyseur de requête:
Voici les tests:
la source
Classe d'encapsuleur chaînable pour HttpValueCollection:
Exemple d'utilisation:
la source
J'ai ajouté la méthode suivante à ma classe PageBase.
Appeler:
la source
J'ai écrit quelques méthodes d'extension que j'ai trouvées très utiles lorsque je travaillais avec QueryStrings. Souvent, je veux commencer par la chaîne de requête actuelle et la modifier avant de l'utiliser. Quelque chose comme,
Pour plus d'informations et la source: http://www.charlesrcook.com/archive/2008/07/23/c-extension-methods-for-asp.net-query-string-operations.aspx
C'est basique, mais j'aime le style.
la source
Je voulais juste jeter mes 2 cents:
Les documents disent que
uri.Query
cela commencera par un?
s'il n'est pas vide et que vous devez le couper si vous souhaitez le modifier.Notez que cela
HttpUtility.UrlEncode
se trouve dansSystem.Web
.Usage:
la source
Bien que n'étant pas élégant, j'ai opté pour une version plus simple qui n'utilise pas
NameValueCollecitons
- juste un modèle de constructeur enroulé autourStringBuilder
.Selon les réponses existantes, je me suis assuré d'utiliser les
HttpUtility.UrlEncode
appels. Il est utilisé comme ça:la source
Production:
Le code; vous pouvez tous me remercier quelque part, en quelque sorte: D
la source
Je suis allé avec la solution proposée par DSO (réponse le 2 août 11 à 7:29), sa solution ne nécessite pas d'utiliser HttpUtility. Cependant, selon un article publié dans Dotnetpearls , l'utilisation d'un dictionnaire est plus rapide (en termes de performances) que l'utilisation de NameValueCollection. Voici la solution de DSO modifiée pour utiliser Dictionary à la place de NameValueCollection.
la source
La chaîne de requête peut être ajoutée à une URL par:
https://blog.codingnovice.com/blog
la source
J'ai écrit une aide pour mon projet de rasoir en utilisant certains des indices d'autres réponses.
L'activité ParseQueryString est nécessaire car nous ne sommes pas autorisés à falsifier l'objet QueryString de la demande en cours.
Je l'utilise comme ceci:
Si vous souhaitez qu'il prenne plusieurs valeurs, modifiez simplement les paramètres en Dictionnaire et ajoutez les paires à la chaîne de requête.
la source
Le code ci-dessous est retiré de l'
HttpValueCollection
implémentation deToString
, via ILSpy, qui vous donne une chaîne de nom = valeur.Malheureusement, HttpValueCollection est une classe interne que vous ne récupérez que si vous l'utilisez
HttpUtility.ParseQueryString()
. Je lui ai supprimé toutes les parties du viewstate, et il code par défaut:la source
Ceci est identique à la réponse acceptée sauf légèrement plus compact:
la source
Juste pour ceux qui ont besoin de la version VB.NET de la première réponse:
Et la version sans LINQ:
Et la version C # sans LINQ:
la source