C# – Senden von Abfragezeichenfolgen mit HttpClient

C# – Senden von Abfragezeichenfolgen mit HttpClient

Abfragezeichenfolgen beginnen mit „?“ und haben ein oder mehrere Schlüssel-Wert-Paare, die durch „&“ getrennt sind. Alle Zeichen außer a-z, A-Z, 0-9 müssen codiert werden, einschließlich Unicode-Zeichen.

Wenn Sie HttpClient verwenden, codiert es den URI automatisch für Sie (intern delegiert es diese Aufgabe an die Uri-Klasse). Das bedeutet, wenn Sie eine Abfragezeichenfolge in den URI einfügen, müssen Sie sie nicht selbst codieren.

Hier ist ein Beispiel für das Senden einer Anfrage mit einer Abfragezeichenfolge:

await httpClient.GetAsync("https://localhost:12345/movies/search?name=John Wick&hasWords=Ελληνικά");
Code language: C# (cs)

Hier ist die eigentliche Anfrage:

GET https://localhost:12345/movies/search?name=John%20Wick&hasWords=%CE%95%CE%BB%CE%BB%CE%B7%CE%BD%CE%B9%CE%BA%CE%AC HTTP/1.1Code language: plaintext (plaintext)

Es kodierte „John Wick“ als „John%20Wick“ und Ελληνικά, das aus Unicode-Zeichen im griechischen Alphabet besteht, als „%CE%95%CE%BB%CE%BB%CE%B7%CE%BD% CE%B9%CE%BA%CE%AC'.

Sie können die Abfragezeichenfolge entweder wie oben gezeigt fest codieren oder sie erstellen. Die einfachste Methode zum Erstellen der Abfragezeichenfolge ist die Verwendung von QueryHelpers.AddQueryString() (von Microsoft.AspNetCore.WebUtilities). Ich werde unten zeigen, wie Sie das verwenden und wie Sie Ihren eigenen Query-String-Builder erstellen.

Erstellen einer Abfragezeichenfolge mit QueryHelpers.AddQueryString()

Hier ist ein Beispiel für die Verwendung von QueryHelpers zum Erstellen einer Abfragezeichenfolge:

using Microsoft.AspNetCore.WebUtilities;

var query = new Dictionary<string, string>()
{
	["name"] = "Dune",
	["year"] = "2021"
};

var uri = QueryHelpers.AddQueryString("https://localhost:12345/movies/search", query);

var result = await httpClient.GetAsync(uri);
Code language: C# (cs)

Hier ist die eigentliche Anfrage:

GET https://localhost:12345/movies/search?name=Dune&year=2021 HTTP/1.1Code language: plaintext (plaintext)

Holen Sie sich Microsoft.AspNetCore.WebUtilities

QueryHelpers befindet sich im Microsoft.AspNetCore.WebUtilities-Paket. Wenn Sie nicht an einem ASP.NET Core-Projekt arbeiten, können Sie das Paket hinzufügen (Ansicht> Andere Fenster> Paket-Manager-Konsole) :

Install-Package Microsoft.AspNetCore.WebUtilities
Code language: PowerShell (powershell)

Dies ist für .NET Standard 2.0 verfügbar, was bedeutet, dass es funktioniert in:.NET Core 1.0+, .NET Framework 4.6.1+, .NET 5+, Unity 2018.1+ und mehr.

Was passiert, wenn Sie einen verschlüsselten URI an HttpClient übergeben?

QueryHelpers.AddQueryString() formatiert und codiert die Abfragezeichenfolge. Da HttpClient den URI bereits codiert, fragen Sie sich vielleicht, was passiert, wenn Sie ihm eine codierte Abfragezeichenfolge übergeben? Keine Sorge, es wird nicht doppelt codiert.

Hier ist ein Beispiel für die Übergabe einer verschlüsselten Abfragezeichenfolge:

await httpClient.GetAsync("https://localhost:12345/movies/search?name=John%20Wick&hasWords=%CE%95%CE%BB%CE%BB%CE%B7%CE%BD%CE%B9%CE%BA%CE%AC")
Code language: C# (cs)

Es wird dies so senden, wie es ist, da der URI bereits codiert ist. Hier ist die eigentliche Anfrage:

GET https://localhost:12345/movies/search?name=John%20Wick&hasWords=%CE%95%CE%BB%CE%BB%CE%B7%CE%BD%CE%B9%CE%BA%CE%AC HTTP/1.1Code language: plaintext (plaintext)

Mit Ihrem eigenen Query-String-Builder

Angenommen, Sie möchten das Paket „Microsoft.AspNetCore.WebUtilities“ nicht hinzufügen oder vielleicht anpassen, wie die Abfragezeichenfolgen erstellt werden. In diesem Fall können Sie Ihren eigenen Query-String-Generator verwenden, indem Sie den QueryHelper.AddQueryString()-Quellcode als Ausgangspunkt verwenden.

Hier ist eine abgespeckte Version mit entfernter Codierung:

public static class RequestUriUtil
{
	public static string GetUriWithQueryString(string requestUri, 
		Dictionary<string, string> queryStringParams)
	{
		bool startingQuestionMarkAdded = false;
		var sb = new StringBuilder();
		sb.Append(requestUri);
		foreach (var parameter in queryStringParams)
		{
			if (parameter.Value == null)
			{
				continue;
			}

			sb.Append(startingQuestionMarkAdded ? '&' : '?');
			sb.Append(parameter.Key);
			sb.Append('=');
			sb.Append(parameter.Value);
			startingQuestionMarkAdded = true;
		}
		return sb.ToString();
	}
}
Code language: C# (cs)

QueryHelpers codiert die Schlüssel/Werte (z. B.:UrlEncoder.Default.Encode(parameter.Key)), während dieser Code nur die Formatierung durchführt. Denken Sie daran, dass HttpClient es automatisch kodiert, daher ist es nicht notwendig, hier zu kodieren.

Hier ist ein Beispiel für die Verwendung dieses Query-String-Builders:

var query = new Dictionary<string, string>()
{
	["name"] = "John Wick",
	["year"] = "2014",
	["hasWords"] = "Ελληνικά"
};

var requestUriWithQuery = RequestUriUtil.GetUriWithQueryString("https://localhost:12345/movies/search", query);

var result = await httpClient.GetAsync(requestUriWithQuery);
Code language: C# (cs)

Hier ist die eigentliche Anfrage:

GET https://localhost:12345/movies/search?name=John%20Wick&year=2014&hasWords=%CE%95%CE%BB%CE%BB%CE%B7%CE%BD%CE%B9%CE%BA%CE%AC HTTP/1.1Code language: plaintext (plaintext)

HttpClient GetWithQueryStringAsync()-Erweiterungsmethode

Wenn Sie HttpClient und einen Generator für Abfragezeichenfolgen verwenden, möchten Sie möglicherweise eine Erweiterungsmethode verwenden, um den aufrufenden Code zu vereinfachen (und möglicherweise Duplikate zu entfernen):

using Microsoft.AspNetCore.WebUtilities;

public static class HttpClientExtensions
{
	public static async Task<HttpResponseMessage> GetWithQueryStringAsync(this HttpClient client, string uri, 
		Dictionary<string, string> queryStringParams)
	{
		var url = QueryHelpers.AddQueryString(uri, queryStringParams);

		return await client.GetAsync(url);
	}
}
Code language: C# (cs)

Verwenden Sie es wie folgt:

var query = new Dictionary<string, string>()
{
	["name"] = "Dune",
	["year"] = "2021"
};

var result = await httpClient.GetWithQueryStringAsync("https://localhost:12345/movies/search", query);
Code language: C# (cs)

HttpClient verfügt über viele Methoden mit vielen Überladungen, sodass Sie dies als Ausgangspunkt verwenden können, um Wrapper für die von Ihnen verwendeten Methoden hinzuzufügen.

Dies ist besonders nützlich, wenn Sie Ihren eigenen Query-String-Builder verwenden, da Sie ihn zu einer privaten Methode machen können, die nur von den HttpClient-Erweiterungsmethoden verwendet wird:

public static class HttpClientExtensions
{
	public static async Task<HttpResponseMessage> GetWithQueryStringAsync(this HttpClient client, string uri,
		Dictionary<string, string> queryStringParams)
	{
		var url = GetUriWithQueryString(uri, queryStringParams);

		return await client.GetAsync(url);
	}

	private static string GetUriWithQueryString(string requestUri,
			Dictionary<string, string> queryStringParams)
	{
		bool startingQuestionMarkAdded = false;
		var sb = new StringBuilder();
		sb.Append(requestUri);
		foreach (var parameter in queryStringParams)
		{
			if (parameter.Value == null)
			{
				continue;
			}

			sb.Append(startingQuestionMarkAdded ? '&' : '?');
			sb.Append(parameter.Key);
			sb.Append('=');
			sb.Append(parameter.Value);
			startingQuestionMarkAdded = true;
		}
		return sb.ToString();
	}
}
Code language: C# (cs)