C# Microsoft Bot Framework WebChat:禁用上一条消息的AdaptiveCards提交按钮
如何在Microsoft Bot Framework(C#)中的BotChat-AdaptiveCards的上一次对话中禁用输入/提交按钮操作我想象您希望向用户显示一张仅使用一次的卡片,如中所示的日历提醒 机器人的主要功能是拥有与人类相同的通道访问权限,因此它们无法返回并修改已发送的消息(除非特定通道允许像Slack那样进行编辑)。虽然您不能禁用卡中已经是对话历史记录一部分的按钮,但您可以更改bot响应该卡生成的消息的方式。您要做的是跟踪按钮是否已被单击,然后在后续时间单击按钮时做出不同的响应 下面是一些对话框代码的基本示例,可以用三种方式响应消息。如果您键入任何消息并将其发送到bot,它将显示一张带有按钮的卡。如果您单击按钮,它将显示“您做到了!”以及您单击的按钮ID。如果您再次单击同一按钮,它将再次显示“您已经这样做了!”并附加IDC# Microsoft Bot Framework WebChat:禁用上一条消息的AdaptiveCards提交按钮,c#,button,botframework,adaptive-cards,web-chat,C#,Button,Botframework,Adaptive Cards,Web Chat,如何在Microsoft Bot Framework(C#)中的BotChat-AdaptiveCards的上一次对话中禁用输入/提交按钮操作我想象您希望向用户显示一张仅使用一次的卡片,如中所示的日历提醒 机器人的主要功能是拥有与人类相同的通道访问权限,因此它们无法返回并修改已发送的消息(除非特定通道允许像Slack那样进行编辑)。虽然您不能禁用卡中已经是对话历史记录一部分的按钮,但您可以更改bot响应该卡生成的消息的方式。您要做的是跟踪按钮是否已被单击,然后在后续时间单击按钮时做出不同的响应
/// <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,
};
}
//
///您需要这样的标签来标识活动
///它是响应提交按钮生成的。
///
private const string DO_SOMETHING=“DoSomething”;
///
///这将传递到StartAsync方法中的context.Wait()中。
///
专用异步任务消息ReceivedAsync(IDialogContext上下文,
(可等待的结果)
{
var msg=等待结果;
如果(!string.IsNullOrWhiteSpace(msg.Text))
{
//如果msg.Text不是null或空白,则表示用户
//实际上,我们输入了一些东西,我们用一张卡片来回应。
var reply=context.MakeMessage();
var attachment=MakeAdaptiveCardAttachment();
答复.附件.增加(附件);
等待上下文。PostAsync(回复);
}
其他的
{
//如果用户没有键入任何内容,则这可能是一个活动
//这是由“提交”按钮生成的。但我们要确保
//这是通过检查msg.Value实现的。
动态值=消息值;
尝试
{
//如果值没有类型,则将抛出RuntimeBinderException
if(value!=null&&value.type==DO\u SOMETHING)
{
字符串id=value.id;
//检查ID以查看之前是否单击过该特定卡。
如果(!context.PrivateConversationData.ContainsKey(id))
{
//这就是你的机器人如何跟踪点击的内容。
context.PrivateConversationData.SetValue(id,true);
wait context.PostAsync(“你做到了!”+id);
}
其他的
{
wait context.PostAsync(“你已经做了!”+id);
}
}
}
捕获(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException)
{
//响应没有类型(或id)值的消息。
}
}
Wait(MessageReceivedAsync);
}
私有静态附件MakeAdaptiveCardAttachment()
{
var卡=新的自适应卡();
//如果我们想允许多张卡,我们需要识别这张特定的卡
//要单击的卡的实例。
//时间戳可以工作,但GUID可以。
var cardId=Guid.NewGuid().ToString();
Add(newtextblock(){Text=cardd});
card.Actions.Add(新提交()
{
Title=“做点什么”,
//我们在该操作中输入的数据将保持不变。
//我发现设置DataJson比使用Data属性更可靠。
//请注意,如果您的WebApiConfig.cs具有CamelCasePropertyNamesContractResolver
//(这是默认值)并使用大写(Pascal大小写)标识符,
//它们可能会转换为camel大小写,您将无法检索
//具有相同标识符的数据。
DataJson=JsonConvert.SerializeObject(新
{
//我们需要一个类型来区分此操作与其他操作。
类型=做某事,
//我们需要一个id来区分这张卡和其他卡。
id=卡迪德,
}),
});
返回新附件()
{
ContentType=AdaptiveCard.ContentType,
内容=卡片,
};
}
下面是它在Bot框架模拟器中的外观。请注意,即使您单击了一张卡并且无法从该卡获得第一个响应,您仍然可以从另一张卡获得第一个响应
欢迎来到SO。请参观一下。请参见如何提问。你需要提到的是,到目前为止你已经尝试了什么。你面临的问题是什么?我可以问一下你说的聊天是什么意思吗?这是WebChat机器人的简写吗?BotChat-AdaptiveCards是指一个特定的机器人还是教程?另外,我想确定你什么时候想要禁用提交按钮操作。Bot框架有对话、对话框等。您想仅从以前的对话或任何以前的“消息”或什么禁用提交按钮操作吗?如果您正在使用该频道,可能有一种方法:您可以自行完成项目并实现该功能。我仍然在工作,我会发布它作为答复时,它的工作。