Reputation: 41
I'm working on a Bot with the Bot Framework v4 in C#. What I want now is, that after sending an Adaptive Card to the user, with Actions, that I can update this card after the Action is fired. For example, that the button will disappear after the click.
here I have a Solution in NodeJS, but I'm not able to transfer it to C#. Can anybody help?
More Project details: I have an Adaptive Card that looks like this:
This Card will be generated, after I searched with the MS Graph from a SharePoint Library.
The Main Goal is, that i can use the Refiners to update the Card with a new Card from JSON. The "OK" button is a Submit Action which can be catched in the OnMessageActivityAsync Method. The Input Values are in the Activity Value so can create a Filter Method. my Problem is, that I can't update the Card that is already send to the User.
Before I sended the first Card with the Results to the User I write the Activity into a State, so I can Access OnMessageActivityAsync Method, but I'm not sure if this is the right approach.
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
Logger.LogInformation("Running dialog with Message Activity.");
var txt = turnContext.Activity.Text;
dynamic val = turnContext.Activity.Value;
// Check if the activity came from a submit action
if (string.IsNullOrEmpty(txt) && val != null)
{
await turnContext.SendActivityAsync(MessageFactory.Text($"Refiner Language: {val.id_language}"));
await turnContext.SendActivityAsync(MessageFactory.Text($"Refiner MachType: {val.id_type}"));
var r = new StreamReader("Cards/helloCard2.json");
string json = r.ReadToEnd();
AdaptiveCard card = AdaptiveCard.FromJson(json).Card;
var docSearchState = await StateAccessor.GetAsync(turnContext);
Activity activity = docSearchState.Activity;
activity.Attachments = new List<Attachment>() {
new Attachment()
{
Name = "Card",
ContentType = AdaptiveCard.ContentType,
Content = card,
}
};
await turnContext.UpdateActivityAsync(activity);
}
This Code gives me the following Error Message:
fail: Microsoft.Bot.Builder.Integration.AspNet.Core.BotFrameworkHttpAdapter[0]
Exception caught : Error reading JArray from JsonReader. Current JsonReader item is not an array: StartObject. Path 'DocumentSearchState.Activity.attachments.$values[0].content.body'.
Has anybody a good idea to solve this?
Upvotes: 4
Views: 5274
Reputation: 11
You can update adaptive card in channel like MS Teams not in directline. For updating card you need one Accessor to store ActivityId which is generated while sending current message.
var response = await stepContext.Context.SendActivityAsync(reply);
//Customize object to store ID
UserProfile user = new UserProfile(response.Id);
//Accessor to store card values to update it and disable buttons after click
await CardStateAccessor.SetAsync(stepContext.Context, user, cancellationToken);
After this in next waterfallstep you need to write logic to update this posted message.
UserProfile UserDataState = await CardStateAccessor.GetAsync(stepContext.Context, () => new UserProfile());
//Retrive accessor property
//Here I am updating adaptive card
var reply = stepContext.Context.Activity.CreateReply();
string text = File.ReadAllText("./AdaptiveCards/UpdatedYesNo.json");
var cardObj = JsonConvert.DeserializeObject(text);
reply.Attachments = new List<Attachment>()
{
new Attachment(){ContentType="application/vnd.microsoft.card.adaptive",Content=cardObj}
};
//Here you need to assign ID from accessor so that earlier posted msg gets updated
reply.Id = UserDataState.ActivityId;
//Use here UpdateActivityAsync to post updated message
await stepContext.Context.UpdateActivityAsync(reply, cancellationToken);
Just addition info: For me goal was to disable buttons of adaptive card after click. So second time when I was posting adaptive card, I just removed all actions from buttons.
Upvotes: 0
Reputation: 12264
Have a look at this answer to get an idea of how to update Adaptive Cards.
You can either write code to remove the submit action from an Adaptive Card dynamically, or you can have two different versions of your card: one with the submit action and one without.
If you want this whole process to be made easier with prebuilt code that you can install in NuGet packages, feel free to voice your support for these ideas on GitHub:
Upvotes: 1