# Send Query (/sdks/csharp/tutorials/query-send)



## Overview [#overview]

This tutorial builds the RPC half of KubeMQ's request/reply patterns: a **query**, where the caller awaits a handler's data payload instead of just a completion status. Reach for it whenever a caller needs an answer — fetching a record, running a lookup, or asking another service to compute a value on demand. This example runs the sender against a separately running handler to see the full round trip.

`await client.SendQueryAsync(new QueryMessage { ... })` blocks until the handler returns a `QueryResponse` or the `TimeoutInSeconds` window elapses. The returned `response.Body` carries the handler's data payload, and `response.Executed` confirms the handler ran to completion — KubeMQ correlates the reply to this call automatically, so the caller never tracks request IDs itself.

**Gotchas:** the timeout must cover however long the handler takes to run — a slow handler throws `KubeMQTimeoutException` even though the handler eventually succeeds, so start the handler before the sender. `response.Body` is a raw byte span — decode or deserialize it yourself; KubeMQ doesn't interpret the payload. When `Executed` is false, check `response.Error` before assuming the call itself failed.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* C# SDK installed (`dotnet add package KubeMQ.SDK.CSharp`)

## Code [#code]

```csharp title="Program.cs"
// KubeMQ .NET SDK — Queries: Send Query
//
// This example demonstrates sending a query and receiving a data response.
// Queries are request/reply: the sender waits for the handler to return data.
//
// Prerequisites:
//   - KubeMQ server running on localhost:50000
//   - Run Queries.HandleQuery in a separate terminal first
//   - dotnet run

using KubeMQ.Sdk.Client;
using KubeMQ.Sdk.Queries;
using KubeMQ.Sdk.Exceptions;
using System.Text;

await using var client = new KubeMQClient(new KubeMQClientOptions
{
    ClientId = "csharp-queries-send-query-client",
});
await client.ConnectAsync();

Console.WriteLine("Connected to KubeMQ server");

try
{
    var response = await client.SendQueryAsync(new QueryMessage
    {
        Channel = "csharp-queries.send-query",
        Body = Encoding.UTF8.GetBytes("get-user:42"),
        TimeoutInSeconds = 10
    });

    Console.WriteLine($"Query executed: {response.Executed}");
    Console.WriteLine($"Response: {Encoding.UTF8.GetString(response.Body.Span)}");
}
catch (KubeMQTimeoutException)
{
    Console.WriteLine("Query timed out — no handler responded within 10 seconds");
}
catch (KubeMQOperationException ex) when (ex.Message.Contains("timeout", StringComparison.OrdinalIgnoreCase))
{
    Console.WriteLine($"Query timed out — server reported: {ex.Message}");
}

Console.WriteLine("Done.");

// Expected output:
// Connected to KubeMQ server
// Query executed: True
// Response: <handler-response-body>
// Done.

```

## How It Works [#how-it-works]

* `SendQueryAsync` blocks until the handler returns a `QueryResponse` or the `TimeoutInSeconds` window elapses. The returned `response.Body` contains the handler's data payload.
* `response.Executed` confirms the handler ran to completion. Check `response.Error` for a handler-populated error message if `Executed` is false.
* `KubeMQTimeoutException` fires when no handler responds within the timeout — start the Handle Query example in a separate terminal before running this sender.
* Unlike commands, queries are expected to return data. Use `Encoding.UTF8.GetString(response.Body.Span)` or deserialise `response.Body` as JSON to consume the response.

## Related [#related]

* [Pattern overview](/learn/rpc/getting-started)
* [C# SDK Reference](/sdks/csharp/reference)
* [Handle Query](/sdks/csharp/how-to/rpc/query-handle)
* [Cached Query](/sdks/csharp/how-to/rpc/query-cached)
