Overview
CallbackQueryHandler is an abstract base class for handlers that process callback query updates. This handler is triggered when users interact with inline keyboards or other callback mechanisms.
Attribute
[CallbackQueryHandler(importance: 0)]
The importance level of the handler. Higher values are executed first.
Base Class
public abstract class CallbackQueryHandler : AbstractUpdateHandler<CallbackQuery>
Inherits from AbstractUpdateHandler<CallbackQuery> with UpdateType.CallbackQuery.
Properties
The following properties are inherited from AbstractUpdateHandler<CallbackQuery>:
Container
IHandlerContainer<CallbackQuery>
Handler container for the current update.
Telegram Bot client associated with the current container.
Incoming callback query update.
Gets the type-specific data from the callback query. Returns the data string, chat instance, or game short name depending on the callback query type.
The Telegram update being handled.
Additional data associated with the handler execution.
List of successfully passed filters.
Provider for awaiting asynchronous operations.
Methods
Execute
public abstract Task<Result> Execute(
IHandlerContainer<CallbackQuery> container,
CancellationToken cancellation
)
Abstract method to implement your callback query handling logic.
container
IHandlerContainer<CallbackQuery>
required
The handler container with callback query data.
cancellation
CancellationToken
required
Cancellation token for the operation.
Returns: Task<Result> - A result indicating success, fault, or continuation.
Answer
protected async Task Answer(
string? text = null,
bool showAlert = false,
string? url = null,
int cacheTime = 0,
CancellationToken cancellationToken = default
)
Answers the current callback query with optional alert or message.
The text to display in the callback answer. Can show a toast notification or alert.
Whether to show an alert popup instead of a toast notification.
A URL that will be opened by the client.
The maximum amount of time in seconds that the result of the callback query may be cached client-side.
Returns: Task - Completes when the answer is sent.
Response
protected async Task<Message> Response(
string text,
ParseMode parseMode = ParseMode.None,
ReplyParameters? replyParameters = null,
ReplyMarkup? replyMarkup = null,
LinkPreviewOptions? linkPreviewOptions = null,
int? messageThreadId = null,
IEnumerable<MessageEntity>? entities = null,
bool disableNotification = false,
bool protectContent = false,
string? messageEffectId = null,
string? businessConnectionId = null,
bool allowPaidBroadcast = false,
int? directMessageTopicId = null,
SuggestedPostParameters? suggestedPostParameters = null,
CancellationToken cancellationToken = default
)
Sends a response message to the current chat.
The text of the message to send.
parseMode
ParseMode
default:"ParseMode.None"
The parse mode for the message text.
The reply markup for the message.
Returns: Task<Message> - The sent message.
EditMessage
protected async Task<Message> EditMessage(
string text,
ParseMode parseMode = ParseMode.None,
InlineKeyboardMarkup? replyMarkup = null,
IEnumerable<MessageEntity>? entities = null,
LinkPreviewOptions? linkPreviewOptions = null,
CancellationToken cancellationToken = default
)
Edits the current callback message with new text.
The new text of the message.
parseMode
ParseMode
default:"ParseMode.None"
The parse mode for the message text.
The new inline keyboard markup for the message.
Returns: Task<Message> - The edited message.
Examples
Basic Callback Handler
using Telegrator.Handlers;
using Telegrator.Filters;
using Telegram.Bot.Types.Enums;
[CallbackQueryHandler]
[CallbackDataFilter("confirm")]
public class ConfirmHandler : CallbackQueryHandler
{
public override async Task<Result> Execute(
IHandlerContainer<CallbackQuery> container,
CancellationToken cancellation)
{
// Answer the callback query
await Answer("Action confirmed!", showAlert: false);
// Edit the message
await EditMessage(
"✅ Confirmed",
parseMode: ParseMode.Html
);
return Result.Ok();
}
}
Callback with Data Parsing
[CallbackQueryHandler]
[CallbackDataFilter(startsWith: "action:")]
public class ActionHandler : CallbackQueryHandler
{
public override async Task<Result> Execute(
IHandlerContainer<CallbackQuery> container,
CancellationToken cancellation)
{
// TypeData contains the callback data
string action = TypeData.Replace("action:", "");
await Answer($"Processing action: {action}");
// Perform action based on data
switch (action)
{
case "delete":
await EditMessage("❌ Deleted");
break;
case "edit":
await EditMessage("✏️ Ready to edit");
break;
default:
await Answer("Unknown action", showAlert: true);
break;
}
return Result.Ok();
}
}
[CallbackQueryHandler]
[CallbackDataFilter(startsWith: "page:")]
public class PaginationHandler : CallbackQueryHandler
{
public override async Task<Result> Execute(
IHandlerContainer<CallbackQuery> container,
CancellationToken cancellation)
{
// Extract page number from callback data
string pageStr = TypeData.Replace("page:", "");
if (!int.TryParse(pageStr, out int page))
{
await Answer("Invalid page", showAlert: true);
return Result.Ok();
}
// Create new keyboard with updated page
var keyboard = new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData("← Previous", $"page:{page - 1}"),
InlineKeyboardButton.WithCallbackData("Next →", $"page:{page + 1}")
}
});
// Edit message with new content
await EditMessage(
$"Page {page}\n\nContent for page {page}...",
replyMarkup: keyboard
);
// Answer to remove loading state
await Answer();
return Result.Ok();
}
}
[CallbackQueryHandler]
[CallbackDataFilter("warning")]
public class WarningHandler : CallbackQueryHandler
{
public override async Task<Result> Execute(
IHandlerContainer<CallbackQuery> container,
CancellationToken cancellation)
{
await Answer(
"⚠️ This action cannot be undone!",
showAlert: true
);
return Result.Ok();
}
}
Best Practices
- Always answer callback queries: Failing to call
Answer() will leave the button in a loading state.
- Use showAlert sparingly: Alerts interrupt the user experience; use them only for important notifications.
- Edit messages efficiently: Use
EditMessage() to update existing messages rather than sending new ones.
- Structure callback data: Use prefixes or delimiters to encode multiple pieces of information in callback data.
See Also