Mittelstand Radar: Kaufsignale aus dem deutschen Mittelstand — jetzt die erste Report-Ausgabe sichern.Zur Warteliste
Ein HTTP-Request mit dem Verb QUERY trägt einen JSON-Body zu einem Server, daneben das .NET-Logo und Symbole für Caching und Wiederholbarkeit
Zurück zum Blog
HTTP.NETASP.NET Core

Die neue HTTP-Methode QUERY – und wie du sie heute schon mit .NET 10 nutzt

Sascha KieferEntwicklung

Suche per GET sprengt irgendwann die URL, Suche per POST ist weder safe noch idempotent noch cachebar. Die neue HTTP-Methode QUERY (RFC 10008) schließt genau diese Lücke: ein Request-Body wie bei POST, aber mit den Garantien von GET. Wir schauen, welches Problem QUERY löst, was die Semantik im Detail bedeutet – und wie .NET 10 die Methode schon heute auf Client- und Serverseite unterstützt.

Jede REST-API kommt irgendwann an denselben Punkt: Du baust einen Such-Endpunkt, der Filter, Sortierung, Paging und ein paar verschachtelte Bedingungen entgegennehmen soll – und plötzlich passt das nicht mehr sauber in eine URL.

Du hast genau zwei schlechte Optionen. Entweder presst du alles in die Query-String einer GET-Anfrage und läufst irgendwann gegen Längenlimits, Encoding-Hölle und die Tatsache, dass sich verschachtelte Strukturen in ?filter[and][0][price][lt]=30 nur noch von Maschinen lesen lassen. Oder du machst aus der Suche ein POST – und gibst damit still alles auf, was eine Suche eigentlich ausmacht: Sie ist safe, idempotent und cachebar.

Genau diese Lücke schließt eine neue HTTP-Methode: QUERY. Seit Juni 2026 ist sie als RFC 10008 offiziell ein Proposed Standard – und das Beste: Mit .NET 10 kannst du sie schon heute einsetzen.

Das Problem: Suchen hat in HTTP nie richtig gepasst

Schauen wir uns an, warum die bestehenden Methoden alle nicht ideal sind.

GET mit Query-String. Korrekt im Sinne der Semantik – safe, idempotent, cachebar. Aber URLs haben in der Praxis Grenzen: Proxies, Server und Browser kappen sie oft bei wenigen Kilobyte. Komplexe Filter mit Arrays und verschachtelten Bedingungen lassen sich nur mühsam und unleserlich kodieren.

GET mit Body. Klingt verlockend, ist aber ein Minenfeld. HTTP definiert für einen Body bei GET keine Semantik, und – Zitat aus der Spezifikation – „verschiedene Client-, Proxy- und Webserver-Implementierungen behandeln GET-Requests mit Body unterschiedlich". Manche ignorieren den Body, manche verwerfen den Request. In der Praxis unbrauchbar.

POST als Suche. Der pragmatische Klassiker. Du kannst beliebige Bodies schicken, alles funktioniert – aber POST ist per Definition weder safe noch idempotent. Für eine Suche heißt das konkret:

  • Keine automatischen Retries: Ein Proxy oder eine HTTP-Bibliothek darf ein POST nach einem Verbindungsabbruch nicht einfach erneut senden – es könnte ja etwas verändert haben.
  • Kein Caching: POST-Antworten werden standardmäßig nicht gecacht.
  • Falsche Semantik: POST signalisiert „ich ändere serverseitig Zustand". Für eine reine Suche ist das schlicht gelogen.

Die Lösung: QUERY

QUERY kombiniert das Beste aus beiden Welten. Die Spezifikation bringt es auf den Punkt:

Ein QUERY fordert, dass das Request-Ziel den enthaltenen Content auf eine safe und idempotente Weise verarbeitet und anschließend mit dem Ergebnis dieser Verarbeitung antwortet.

Anders gesagt: QUERY transportiert seine Anfrage im Body – wie POST, mit beliebigem Inhalt und einem Content-Type deiner Wahl. Gleichzeitig garantiert die Methode dieselben Eigenschaften wie GET:

EigenschaftGETQUERYPOST
Safe
Idempotent
Body mit definierter Semantik
Antwort cachebarnur explizit

So ein QUERY-Request sieht roh etwa so aus:

QUERY /products/search HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept: application/json

{
  "category": "books",
  "price": { "lt": 30 },
  "sort": ["-published", "title"],
  "page": { "size": 20, "cursor": "eyJpZCI6NDJ9" }
}

Der Server antwortet mit 200 OK und dem Suchergebnis im Body. Weil die Methode safe und idempotent ist, dürfen Intermediäre den Request bei einem Abbruch gefahrlos wiederholen und die Antwort cachen.

Ein paar Details, die zählen

  • Content-Type ist Pflicht. Der Server muss den Request ablehnen, wenn der Content-Type fehlt oder nicht zum Inhalt passt. Der Medientyp definiert die Abfragesprache – das kann JSON sein, aber genauso application/sql, application/graphql oder ein eigenes Filter-Format.
  • Content-Location im Response. Antwortet der Server mit einem Content-Location-Header, zeigt dieser auf eine Ressource, die dem Ergebnis entspricht. Clients können diese URL später per GET abrufen – so lässt sich aus einer Suche faktisch eine cachebare Ergebnis-Ressource materialisieren.
  • Sinnvolle Fehlercodes. Fehlt der Content-Type400. Wird der Medientyp nicht unterstützt → 415. Ist die Abfrage syntaktisch ok, aber inhaltlich nicht verarbeitbar → 422. Passt das gewünschte Antwortformat nicht → 406.

Wer steht hinter dem Standard?

QUERY kommt aus der IETF HTTP Working Group (httpbis). Geschrieben wurde RFC 10008 von Julian Reschke, James M. Snell (Cloudflare) und Mike Bishop (Akamai) – die Mitwirkung von CDN- und Edge-Anbietern ist kein Zufall, denn von cachebaren Suchanfragen profitieren genau diese Akteure. Die Methode trug während der Entwicklung den Arbeitstitel draft-ietf-httpbis-safe-method-w-body.

Wie weit ist die Verbreitung?

Ehrlich gesagt: Die Semantik ist standardisiert, der Stack ist es noch nicht.

  • Browser können QUERY aktuell nicht aus fetch/XHR heraus senden.
  • Proxies und CDNs cachen QUERY-Antworten in der Breite noch nicht zuverlässig – auch wenn die Autorenschaft von Cloudflare und Akamai die Richtung vorgibt.
  • Frameworks fangen gerade erst an, die Methode zu erkennen.

Und genau hier kommt .NET ins Spiel: .NET 10 (LTS, erschienen im November 2025) gehört zu den ersten Plattformen mit eingebauter QUERY-Unterstützung – auf Client- und Serverseite.

QUERY mit .NET 10: Clientseite

Auf der Client-Seite hat System.Net.Http eine neue Property bekommen: HttpMethod.Query. Kein magischer String mehr, einfach:

using System.Net.Http.Json;

var filter = new ProductFilter("books", MaxPrice: 30);

using var request = new HttpRequestMessage(HttpMethod.Query, "https://api.example.com/products/search")
{
    Content = JsonContent.Create(filter)
};

using var response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();

var page = await response.Content.ReadFromJsonAsync<ProductPage>();

Das war's. HttpClient schickt die Methode QUERY mitsamt Body über die Leitung – und weil .NET die Methode als idempotent kennt, greifen die üblichen Resilienz-Mechanismen (etwa automatische Retries über Microsoft.Extensions.Http.Resilience) genauso, wie du es von GET erwartest.

QUERY mit .NET 10: Serverseite

In ASP.NET Core 10 ist QUERY über zwei neue Bausteine in Microsoft.AspNetCore.Http.HttpMethods verfügbar:

public static readonly string Query = "QUERY";
public static bool IsQuery(string method);

Kestrel parst die Methode bereits und stellt sie als "QUERY" bereit. Damit kannst du in einer Minimal API einen Endpunkt registrieren – über das generische MapMethods:

app.MapMethods("/products/search", new[] { HttpMethods.Query },
    async (HttpContext ctx, ICatalog catalog) =>
    {
        var filter = await ctx.Request.ReadFromJsonAsync<ProductFilter>();
        if (filter is null)
            return Results.BadRequest();

        var page = await catalog.SearchAsync(filter);
        return Results.Ok(page);
    });

Ein kleiner Wermutstropfen – und der Workaround

Der ursprüngliche Vorschlag für ASP.NET Core enthielt komfortable Helfer wie MapQuery(...) und ein [HttpQuery]-Attribut für MVC-Controller. Nach dem API-Review wurden diese aber bewusst aus dem Release herausgeschnitten – in .NET 10 gibt es kein MapQuery und kein [HttpQuery]. Geliefert wurden nur die Primitive.

Macht nichts – die Lücke ist eine Handvoll Zeilen weit:

public static class QueryEndpointExtensions
{
    public static RouteHandlerBuilder MapQuery(
        this IEndpointRouteBuilder endpoints,
        string pattern,
        Delegate handler)
        => endpoints.MapMethods(pattern, new[] { HttpMethods.Query }, handler);
}

Damit liest sich dein Endpunkt wieder so sauber, wie man es erwartet:

app.MapQuery("/products/search", async (ProductFilter filter, ICatalog catalog) =>
    Results.Ok(await catalog.SearchAsync(filter)));

Und wenn du in Middleware oder einem bestehenden Handler auf die Methode verzweigen willst:

if (HttpMethods.IsQuery(context.Request.Method))
{
    // QUERY-spezifische Verarbeitung
}

Was du sonst noch wissen solltest

ASP.NET Core 10 erkennt QUERY auch in der OpenAPI-Generierung: Da OpenAPI 3.1 die Methode (noch) nicht kennt, werden QUERY-Endpunkte beim Erzeugen des Dokuments sauber ausgelassen, statt einen Fehler zu werfen. Wenn deine API stark auf einer OpenAPI-Spec aufbaut, solltest du das im Hinterkopf behalten – die Endpunkte funktionieren, tauchen aber (noch) nicht im generierten Schema auf.

Sollte ich das schon einsetzen?

Kommt darauf an, wer auf der anderen Seite steht.

  • Server-zu-Server, beide Seiten unter deiner Kontrolle (z. B. .NET ↔ .NET): Hier kannst du QUERY heute sinnvoll einsetzen. Client und Server sprechen die Methode, die Semantik passt, und du gewinnst saubere Retries und korrekte Semantik geschenkt.
  • Öffentliche API mit Browser-Clients: Noch nicht. Solange fetch QUERY nicht senden kann, brauchst du ohnehin einen POST-Fallback – dann lohnt der Doppelaufwand selten.
  • Verlass dich noch nicht auf Caching durch Intermediäre. Die Semantik erlaubt es, aber Proxies und CDNs setzen es in der Breite noch nicht um. Behandle das als netten Bonus für später, nicht als heutige Architekturgrundlage.

Der pragmatische Mittelweg: Endpunkte intern schon auf QUERY auslegen (die paar Zeilen MapQuery-Helper kosten nichts), für öffentliche Clients vorerst parallel POST anbieten. So bist du vorbereitet, wenn der Rest des Stacks nachzieht.

Fazit

QUERY ist eine dieser Standardisierungen, die ein Problem lösen, mit dem sich praktisch jedes API-Team schon einmal herumgeschlagen hat – die Suche, die in keine URL passt und für die POST semantisch falsch ist. Die Methode gibt dir den Body von POST mit den Garantien von GET: safe, idempotent, cachebar.

Mit RFC 10008 ist die Semantik festgezurrt, und .NET 10 gehört zu den ersten Plattformen, die sie ausliefern – HttpMethod.Query auf dem Client, HttpMethods.Query und HttpMethods.IsQuery auf dem Server. Die Browser und CDNs brauchen noch etwas, aber für Service-zu-Service-Kommunikation in der .NET-Welt kannst du QUERY heute sauber nutzen. Und mit einem winzigen Extension-Helper liest es sich, als hätte das Framework MapQuery von Anfang an mitgeliefert.

Brauchst du Unterstützung?

Baust du APIs, die mehr leisten müssen als simple CRUD-Endpunkte – komplexe Suchen, saubere HTTP-Semantik, resiliente Service-Kommunikation? Wir helfen Teams, ihre .NET-Schnittstellen zukunftsfest aufzustellen: von der richtigen Methodenwahl über Caching-Strategien bis zu belastbaren Retry- und Resilienz-Patterns. Melde dich einfach bei uns – wir bringen deine APIs auf den aktuellen Stand der Technik.

Kontakt aufnehmen