Wenn ich eine http get-Anfrage mit System.Net.HttpClient senden möchte, scheint es keine API zum Hinzufügen von Parametern zu geben. Ist dies korrekt?
Gibt es eine einfache API zum Erstellen der Abfragezeichenfolge, bei der keine Namenswertsammlung und URL-Codierung erstellt und diese schließlich verkettet werden? Ich hatte gehofft, so etwas wie RestSharps API zu verwenden (dh AddParameter (..))
Antworten:
Ja.
Sicher:
gibt Ihnen das erwartete Ergebnis:
Möglicherweise finden Sie die
UriBuilder
Klasse auch nützlich:gibt Ihnen das erwartete Ergebnis:
dass Sie Ihre
HttpClient.GetAsync
Methode mehr als sicher füttern könnten .quelle
#
mithilfe der Fragment-Eigenschaft sogar URLs mit fragment ( ) für Sie. Ich habe so viele Leute gesehen, die den Fehler gemacht haben, URLs manuell zu verarbeiten, anstatt die integrierten Tools zu verwenden.NameValueCollection.ToString()
Normalerweise werden keine Abfragezeichenfolgen erstellt, und es gibt keine Dokumentation, die besagt, dass das Ausführen einesToString
Ergebnisses vonParseQueryString
zu einer neuen Abfragezeichenfolge führt und daher jederzeit unterbrochen werden kann, da für diese Funktionalität keine Garantie besteht.Für diejenigen , die nicht berücksichtigt werden sollen
System.Web
nicht bereits in Projekte , die Sie verwenden, können SieFormUrlEncodedContent
ausSystem.Net.Http
und etwas tun , wie folgt aus :keyvaluepair version
Wörterbuchversion
quelle
dispose
? Ich verfüge immer, es sei denn, ich habe einen guten Grund, es nicht wiederzuverwendenHttpClient
.TL; DR: Verwenden Sie keine akzeptierte Version, da diese in Bezug auf die Behandlung von Unicode-Zeichen völlig fehlerhaft ist, und verwenden Sie niemals die interne API
Ich habe tatsächlich ein seltsames Problem mit der doppelten Codierung bei der akzeptierten Lösung festgestellt:
Wenn Sie also mit Zeichen arbeiten, die codiert werden müssen, führt eine akzeptierte Lösung zu einer doppelten Codierung:
NameValueCollection
Indexers automatisch codiert ( und dies verwendetUrlEncodeUnicode
nicht regelmäßig erwartetUrlEncode
(!) ).uriBuilder.Uri
, wird ein neuerUri
Konstruktor erstellt, der die Codierung noch einmal ausführt (normale URL-Codierung).uriBuilder.ToString()
Dies kann nicht vermieden werden, indem Sie (obwohl dies korrekt zurückgibt,Uri
welche IMO zumindest inkonsistent ist, möglicherweise ein Fehler, aber das ist eine andere Frage) und dann eineHttpClient
Methode verwenden, die eine Zeichenfolge akzeptiert - der Client erstellt immer nochUri
aus Ihrer übergebenen Zeichenfolge Folgendes:new Uri(uri, UriKind.RelativeOrAbsolute)
Kleiner, aber voller Repro:
Ausgabe:
Wie Sie vielleicht sehen, egal ob Sie
uribuilder.ToString()
+httpClient.GetStringAsync(string)
oderuriBuilder.Uri
+ tunhttpClient.GetStringAsync(Uri)
senden Sie , doppelt codierte ParameterEin behobenes Beispiel könnte sein:
Dies verwendet jedoch einen veralteten
Uri
KonstruktorPS in meinem neuesten .NET unter Windows Server,
Uri
Konstruktor mit bool doc Kommentar sagt "veraltet, dontEscape ist immer falsch", funktioniert aber tatsächlich wie erwartet (überspringt das Escapezeichen)Es sieht also nach einem weiteren Fehler aus ...
Und selbst das ist einfach falsch - es sendet UrlEncodedUnicode an den Server, nicht nur UrlEncoded, was der Server erwartet
Update: Eine weitere Sache ist, dass NameValueCollection tatsächlich UrlEncodeUnicode ausführt, das nicht mehr verwendet werden soll und nicht mit regulärem url.encode / decode kompatibel ist (siehe NameValueCollection to URL Query? ).
Das Fazit lautet also: Verwenden Sie diesen Hack niemals,
NameValueCollection query = HttpUtility.ParseQueryString(builder.Query);
da dies Ihre Unicode-Abfrageparameter durcheinander bringt. Erstellen Sie die Abfrage einfach manuell und weisen Sie sieUriBuilder.Query
der erforderlichen Codierung zu, und verwenden Sie dann UriUriBuilder.Uri
.Paradebeispiel dafür, wie Sie sich selbst verletzen, indem Sie Code verwenden, der nicht so verwendet werden soll
quelle
var namedValues = HttpUtility.ParseQueryString(builder.Query)
, aber anstatt die zurückgegebene NameValueCollection zu verwenden, konvertieren Sie sie sofort in ein Wörterbuch wie folgt:var dic = values.ToDictionary(x => x, x => values[x]);
Fügen Sie dem Wörterbuch neue Werte hinzu, übergeben Sie es an den Konstruktor vonFormUrlEncodedContent
und rufen SieReadAsStringAsync().Result
es auf. Dadurch erhalten Sie eine ordnungsgemäß codierte Abfragezeichenfolge, die Sie dem UriBuilder zurückweisen können.<add key="aspnet:DontUsePercentUUrlEncoding" value="true" />
. Ich würde mich nicht auf dieses Verhalten verlassen, daher ist es besser, die FormUrlEncodedContent-Klasse zu verwenden, wie eine frühere Antwort zeigt: stackoverflow.com/a/26744471/88409In einem ASP.NET Core-Projekt können Sie die QueryHelpers-Klasse verwenden.
quelle
Vielleicht möchten Sie sich Flurl [Offenlegung: Ich bin der Autor] ansehen , einen fließenden URL-Builder mit optionaler Companion-Bibliothek, der ihn zu einem vollständigen REST-Client erweitert.
Auschecken Weitere Informationen finden den Dokumenten . Das vollständige Paket ist auf NuGet verfügbar:
PM> Install-Package Flurl.Http
oder nur der eigenständige URL-Builder:
PM> Install-Package Flurl
quelle
Uri
oder mit Ihrer eigenen Klasse beginnen, anstattstring
?Url
Klasse angefangen. Das Obige entsprichtnew Url("https://api.com").AppendPathSegment...
Persönlich. Ich bevorzuge die Zeichenfolgenerweiterungen aufgrund weniger Tastenanschläge und standardisiert in den Dokumenten, aber Sie können es so oder so tun.In Anlehnung an Rostovs Beitrag können Sie from verwenden , wenn Sie keinen Verweis auf
System.Web
in Ihr Projekt aufnehmen möchtenFormDataCollection
System.Net.Http.Formatting
und etwas tun , wie folgt aus :Verwenden von
System.Net.Http.Formatting.FormDataCollection
quelle
Darin bot eine interessante und clevere Lösung an, und hier ist etwas, das eine andere Option sein könnte:
Wenn Sie es verwenden, können Sie Folgendes tun:
quelle
kvp.Key
undkvp.Value
nicht für Schleife in der separat in der vollständigen Abfrage-String (also nicht die Codierung&
und=
Zeichen).server.UrlEncode
kann die durchWebUtility.UrlEncode
Oder einfach mit meiner Uri-Erweiterung
Code
Verwendung
Ergebnis
quelle
Die von mir entwickelte RFC 6570-URI-Vorlagenbibliothek kann diesen Vorgang ausführen. Die gesamte Codierung wird gemäß diesem RFC für Sie behandelt. Zum Zeitpunkt dieses Schreibens ist eine Beta-Version verfügbar und der einzige Grund, warum sie nicht als stabile Version 1.0 angesehen wird, ist, dass die Dokumentation meine Erwartungen nicht vollständig erfüllt (siehe Probleme Nr. 17 , Nr. 18 , Nr. 32 , Nr. 43 ).
Sie können entweder nur eine Abfragezeichenfolge erstellen:
Oder Sie können eine vollständige URI erstellen:
quelle
Da ich diese wenigen Male wiederverwenden muss, habe ich mir diese Klasse ausgedacht, die einfach dazu beiträgt, die Zusammensetzung der Abfragezeichenfolge zu abstrahieren.
Die Verwendung wird zu so etwas vereinfacht:
Dadurch wird die URL zurückgegeben: http://example.com/?foo=bar%3c%3e%26-baz&bar=second
quelle
Um das in der Antwort von taras.roshko beschriebene Problem der doppelten Codierung zu vermeiden und die Möglichkeit zu behalten, einfach mit Abfrageparametern zu arbeiten, können Sie
uriBuilder.Uri.ParseQueryString()
stattdessen verwendenHttpUtility.ParseQueryString()
.quelle
Ein großer Teil der akzeptierten Antwort wurde geändert, um UriBuilder.Uri.ParseQueryString () anstelle von HttpUtility.ParseQueryString () zu verwenden:
quelle
ParseQueryString()
Erweiterungsmethode nicht enthalten istSystem
.Dank "Darin Dimitrov" ist dies die Erweiterungsmethode.
quelle
Ich konnte keine bessere Lösung finden, als eine Erweiterungsmethode zum Konvertieren eines Wörterbuchs in QueryStringFormat zu erstellen. Die von Waleed AK vorgeschlagene Lösung ist ebenfalls gut.
Folgen Sie meiner Lösung:
Erstellen Sie die Erweiterungsmethode:
Und sie:
quelle