SOLVED

Getting a past activity's card attachment

%3CLINGO-SUB%20id%3D%22lingo-sub-2092902%22%20slang%3D%22en-US%22%3EGetting%20a%20past%20activity's%20card%20attachment%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2092902%22%20slang%3D%22en-US%22%3E%3CP%3EHi%2C%3C%2FP%3E%3CP%3EOur%20parent%20bot%20displays%20an%20adaptive%20card%20with%20a%20submit%20button.%26nbsp%3B%20When%20the%20user%20clicks%20on%20the%20submit%20button%2C%20a%20skill%20dialog%20bot's%20skill%20is%20invoked.%26nbsp%3B%20When%20the%20parent%20bot%20invokes%20a%20skill%2C%20sometimes%20the%20skill%20bot%20does%20not%20complete%20the%20invocation%20and%20nothing%20gets%20returned%20to%20the%20parent.%26nbsp%3B%20When%20the%20user%20tries%20the%20card%20again%2C%20the%20action%20ends%20up%20with%20the%20skill%20dialog%20bot%20because%20control%20was%20not%20returned%20to%20the%20parent.%26nbsp%3B%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EIn%20the%20following%20code%20snippet%2C%20our%20skill%20dialog%20bot's%20processActivity%20is%20routing%20processing%20logic%20based%20on%20the%20ActivityType%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-javascript%22%3E%3CCODE%3E%20%20%20%20async%20processActivity(stepContext)%20%7B%0A%20%20%20%20%20%20%20%20const%20activity%20%3D%20stepContext.context.activity%3B%0A%20%20%20%20%20%20%20%20switch%20(activity.type)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%20ActivityTypes.Event%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20await%20this.onEventActivity(stepContext)%3B%0A%20%20%20default%3A%0A%20%20%20%20%2F%2F%20We%20didn't%20get%20an%20event%20name%20we%20can%20handle.%0A%20%20%20%20await%20stepContext.context.sendActivity(%0A%20%20%20%20%20%60Unrecognized%20EventName%3A%20%22%24%7B%20stepContext.context.activity.name%20%7D%22.%60%2C%0A%20%20%20%20%20undefined%2C%0A%20%20%20%20%20InputHints.IgnoringInput%0A%20%20%20%20)%3B%0A%20%20%20%20return%20%7B%20status%3A%20DialogTurnStatus.complete%20%7D%3B%0A%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3EWhen%20the%20control%20is%20stuck%20with%20the%20skill%20dialog%20bot%2C%20we%20see%20the%20'Unrecognized%20Eventname'%20in%20our%20logs.%26nbsp%3B%20To%20remediate%20this%2C%20we%20replaced%20the%20default%20section%20with%20the%20following%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-javascript%22%3E%3CCODE%3E%20%20%20%20%20%20%20%20%20%20%20%20default%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20await%20stepContext.context.sendActivity(%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20ActivityTypes.EndOfConversation%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20code%3A%20EndOfConversationCodes.CompletedSuccessfully%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20action%3A%20'abort'%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20conversationId%3A%20activity.conversationId%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20activityId%3A%20activity.activityId%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D)%3B%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3EOur%20parent%20bot%20has%20a%20finalStep%20that%20processes%20the%20results%20returned%20from%20the%20skill%20dialog%20bot.%26nbsp%3B%26nbsp%3B%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-javascript%22%3E%3CCODE%3Eif%20(stepContext.result.action%20%3D%3D%3D%20'abort')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20console.log('ooops%2C%20skil%20dialog%20bot%20encountered%20an%20error%20and%20triggered%20an%20abort')%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20await%20stepContext.context.sendActivity('I%20am%20sorry%20but%20looks%20like%20one%20of%20my%20skills%20encountered%20an%20error.%20%20Can%20you%20try%20again%3F')%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3EInstead%20of%20displaying%20a%20separate%20message%20to%20the%20user%2C%20we%20were%20hoping%20there%20would%20be%20a%20way%20to%20retrieve%20the%20card%20attachment%20of%20the%20activity%20the%20user%20acted%20on%20so%20that%20we%20can%20append%20the%20%22retry%22%20message%20to%20the%20card.%3C%2FP%3E%3CP%3EDoes%20anyone%20know%20if%20we%20can%20retrieve%20a%20past%20activity%20in%20a%20conversation%20based%20on%20an%20activity%20Id%3F%26nbsp%3B%3C%2FP%3E%3CP%3EThank%20You%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-LABS%20id%3D%22lingo-labs-2092902%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EBot%20Framework%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EDeveloper%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EMicrosoft%20Teams%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E
Contributor

Hi,

Our parent bot displays an adaptive card with a submit button.  When the user clicks on the submit button, a skill dialog bot's skill is invoked.  When the parent bot invokes a skill, sometimes the skill bot does not complete the invocation and nothing gets returned to the parent.  When the user tries the card again, the action ends up with the skill dialog bot because control was not returned to the parent.  

 

In the following code snippet, our skill dialog bot's processActivity is routing processing logic based on the ActivityType

 

    async processActivity(stepContext) {
        const activity = stepContext.context.activity;
        switch (activity.type) {
            case ActivityTypes.Event:
                return await this.onEventActivity(stepContext);
			default:
				// We didn't get an event name we can handle.
				await stepContext.context.sendActivity(
					`Unrecognized EventName: "${ stepContext.context.activity.name }".`,
					undefined,
					InputHints.IgnoringInput
				);
				return { status: DialogTurnStatus.complete };
			}
        }
    }

When the control is stuck with the skill dialog bot, we see the 'Unrecognized Eventname' in our logs.  To remediate this, we replaced the default section with the following

            default:
                return await stepContext.context.sendActivity({
                    type: ActivityTypes.EndOfConversation,
                    code: EndOfConversationCodes.CompletedSuccessfully,
                    value: {
                        action: 'abort',
                        conversationId: activity.conversationId,
                        activityId: activity.activityId
                    }
                });

Our parent bot has a finalStep that processes the results returned from the skill dialog bot.  

if (stepContext.result.action === 'abort') {
                    console.log('ooops, skil dialog bot encountered an error and triggered an abort')
                    await stepContext.context.sendActivity('I am sorry but looks like one of my skills encountered an error.  Can you try again?')
                } 

Instead of displaying a separate message to the user, we were hoping there would be a way to retrieve the card attachment of the activity the user acted on so that we can append the "retry" message to the card.

Does anyone know if we can retrieve a past activity in a conversation based on an activity Id? 

Thank You

3 Replies

Hi @voonsionglum, yes it is possible to retrieve the ID of the past activity conversation and can also update the activity using UpdateActivityAsync method. Could you please have a look at this sample code.

@Mallipriya_MSFT Thanks for the response.  We want to retrieve the actual card body of a previous activity.  With a given activity Id, do you know if we can get the content that was sent for that activity?  We would like to be able to amend the content of a previous activity (especially when the activity is sending a card) so that we can add in error messages if something went wrong with the bot.  

 

It would be like how cards show the "Unable to reach app" red text message on adaptive cards when submit actions for cards are unable to complete when the corresponding web app is down.

best response confirmed by voonsionglum (Contributor)
Solution

Hi @voonsionglum, To retrieve the actual card body of a previous activity, there is no direct way to achieve it. Rather, you can try using messageID/ Conversation ID (we get in TurnContext object), build the conversation reference and save it in Azure Table Storage or Azure Blob Storage and update the previously posted card using updateActivityAsync method.  

www.000webhost.com