简体   繁体   中英

Update already posted Adaptive Card in Bot Framework v4 in C#

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.

Link to NodeJS Solution

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?

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:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM