[英]Microsoft Bot Framework WebChat: Disable AdaptiveCards submit buttons of previous message
如何在BotChat的前一个对话中禁用输入/提交按钮操作 - Microsoft Bot框架中的AdaptiveCards(C#)
I'm imagining you want to display a card to the user that's meant to be used only once, such as a calendar reminder like the one seen in this example . 我想象你想要向用户显示一张只能使用一次的卡片,例如像本例中所见的日历提醒。
Bots are mostly meant to have the same kind of access to a channel that a human would, so they can't go back and modify the messages that have already been sent (unless the specific channel allows edits like Slack does). 机器人通常意味着对人类所拥有的频道具有相同类型的访问权限,因此他们无法返回并修改已发送的消息(除非特定频道允许像Slack这样的编辑)。 While you can't disable a button in a card that's already part of the conversation history, you can change the way your bot responds to the messages that are generated by that card.
虽然您无法禁用已经属于对话历史记录的卡中的按钮,但您可以更改机器人响应该卡生成的消息的方式。 What you'll want to do is keep track of whether a button has been clicked and then respond differently when the button is clicked subsequent times.
您要做的是跟踪按钮是否被单击,然后在随后单击按钮时以不同方式响应。
Here's a basic example of some Dialog code that can respond to messages in three ways. 以下是一些可以通过三种方式响应消息的Dialog代码的基本示例。 If you type any message and send it to the bot, it will display a card with a button on it.
如果您键入任何消息并将其发送到机器人,它将显示一张卡片,上面有一个按钮。 If you click the button, it will say "You did it!"
如果单击按钮,它会显示“你做到了!” along with the ID of the button you clicked.
以及您单击的按钮的ID。 If you click the same button again, it will say "You already did that!"
如果再次单击相同按钮,则会显示“您已经这样做了!” again attaching the ID.
再次附上身份证。
/// <summary>
/// You'll want a label like this to identify the activity
/// that gets generated in response to your submit button.
/// </summary>
private const string DO_SOMETHING = "DoSomething";
/// <summary>
/// This is passed into context.Wait() in your StartAsync method.
/// </summary>
private async Task MessageReceivedAsync(IDialogContext context,
IAwaitable<IMessageActivity> result)
{
var msg = await result;
if (!string.IsNullOrWhiteSpace(msg.Text))
{
// If msg.Text isn't null or white space then that means the user
// actually typed something, and we're responding to that with a card.
var reply = context.MakeMessage();
var attachment = MakeAdaptiveCardAttachment();
reply.Attachments.Add(attachment);
await context.PostAsync(reply);
}
else
{
// If the user didn't type anything then this could be an activity
// that was generated by your submit button. But we want to make sure
// it is by checking msg.Value.
dynamic value = msg.Value;
try
{
// If value doesn't have a type then this will throw a RuntimeBinderException
if (value != null && value.type == DO_SOMETHING)
{
string id = value.id;
// Check the ID to see if that particular card has been clicked before.
if (!context.PrivateConversationData.ContainsKey(id))
{
// This is how your bot will keep track of what's been clicked.
context.PrivateConversationData.SetValue(id, true);
await context.PostAsync("You did it! " + id);
}
else
{
await context.PostAsync("You already did that! " + id);
}
}
}
catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException)
{
// Respond to messages that don't have values with a type (or id).
}
}
context.Wait(MessageReceivedAsync);
}
private static Attachment MakeAdaptiveCardAttachment()
{
var card = new AdaptiveCard();
// We need to identify this specific card if we want to allow multiple
// instances of the card to be clicked.
// A timestamp could work but a GUID will do.
var cardId = Guid.NewGuid().ToString();
card.Body.Add(new TextBlock() { Text = cardId });
card.Actions.Add(new SubmitAction()
{
Title = "Do something",
// The data we put inside this action will persist.
// I've found setting DataJson to be more reliable than using the Data property.
// Note that if your WebApiConfig.cs has a CamelCasePropertyNamesContractResolver
// (which is a default) and you use capitalized (Pascal case) identifiers,
// they may be converted to camel case and you won't be able to retrieve
// the data with the same identifiers.
DataJson = JsonConvert.SerializeObject(new
{
// We need a type to differentiate this action from other actions.
type = DO_SOMETHING,
// We need an id to differentiate this card from other cards.
id = cardId,
}),
});
return new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = card,
};
}
Here's what it looks like in Bot Framework Emulator. 这是它在Bot框架模拟器中的样子。 Note that even after you've clicked one card and can't get the first response from that card, you can still get the first response from the other card.
请注意,即使您点击了一张卡并且无法从该卡获得第一个响应,您仍然可以从另一张卡获得第一个响应。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.