Microsoft Bot Framework WebChat:禁用AdaptiveCard提交上一条消息的按钮

时间:2018-08-06 05:23:59

标签: c# button botframework adaptive-cards web-chat

如何在上一次BotChat对话中禁用输入/提交按钮操作-Microsoft Bot Framework(C#)中的AdaptiveCards

1 个答案:

答案 0 :(得分:2)

我在想您要向用户显示只能使用一次的卡片,例如this example中显示的日历提醒。

大多数情况下,漫游器都具有与人类相同的访问通道的权限,因此它们无法返回并修改已发送的消息(除非特定的通道允许像Slack一样进行编辑)。虽然您不能禁用对话历史记录中已经包含的卡片中的按钮,但是您可以更改漫游器对该卡片生成的消息的响应方式。您要做的就是跟踪是否已单击某个按钮,然后在随后单击该按钮时做出不同的反应。

这是一些可以以三种方式响应消息的对话框代码的基本示例。如果您键入任何消息并将其发送到机器人,它将显示带有按钮的卡。如果单击该按钮,它将显示“您完成了!”。以及您单击的按钮的ID。如果再次单击同一按钮,则会显示“您已经这样做了!”。再次附加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,
    };
}

这是Bot Framework Emulator中的外观。请注意,即使您单击了一张卡片后仍无法从该卡片获得第一响应,仍然可以从另一张卡片获得第一响应。

enter image description here

相关问题